package com.zb.mobile.network.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zb.callback.service.impl.LKaiPushServiceImpl;
import com.zb.constant.NetworkConstant;
import com.zb.constant.WorkConstant;
import com.zb.excel.converter.WorkConverter;
import com.zb.entity.*;
import com.zb.exception.SMSException;
import com.zb.extend.*;
import com.zb.mapper.ZjWorkSlaConditionMapper;
import com.zb.mapper.ZjWorkSlaModuleMapper;
import com.zb.mobile.*;
import com.zb.mobile.network.service.ConNetworkOrderMobileService;
import com.zb.order.service.ConWorkOrderService;
import com.zb.order.service.WorkSlaUtilService;
import com.zb.result.PageUtil;
import com.zb.service.*;
import com.zb.service.impl.WorkServiceLog;
import com.zb.service.SmsVerificCodeService;
import com.zb.service.impl.WorkUtilService;
import com.zb.sms.entity.SendOrderFinishVo;
import com.zb.sms.entity.SendOrderReservationTimeVo;
import com.zb.sms.service.SmsSendMessageService;
import com.zb.utils.ZbDateConvertUtil;
import com.zb.utils.ZbDateUtil;
import com.zb.utils.ZbOrderNoUtil;
import com.zb.view.ViewNetworkEmpAccount;
import com.zb.view.ViewNetworkEmpDetail;
import com.zb.vo.*;
import com.zb.yaml.HoubanYunOrder;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author WEN
 * @Date 2023/11/22 0022
 **/
@Service
@EnableScheduling
public class ConNetworkOrderMobileServiceImpl implements ConNetworkOrderMobileService {
    @Resource
    private ZjNetworkService networkService;
    @Resource
    private ZjNetworkEmpRelationService networkEmpRelationService;
    @Resource
    private ZjWorkOrderService workOrderService;
    @Resource
    private ZjWorkDetailService workDetailService;
    @Resource
    private ZjWorkDispatchEngineerService workDispatchEngineerService;
    @Resource
    private ZjWorkDispatchEngineerCooperateService workDispatchEngineerCooperateService;
    @Resource
    private ZjWorkModuleService workModuleService;
    @Resource
    private ViewNetworkEmpAccountService viewNetworkEmpAccountService;
    @Resource
    private ZjWorkDispatchNetworkService workDispatchNetworkService;
    @Resource
    private ZjWorkUserService workUserService;
    @Resource
    private ZjWorkLeaveMessageService workLeaveMessageService;
    @Resource
    private ZjWorkLeaveMessageAnnexService workLeaveMessageAnnexService;
    @Resource
    private ZjAccountService accountService;
    @Resource
    private ZjUserService userService;
    @Resource
    private ZjWorkLevelService workLevelService;
    @Resource
    private ZjWorkImageService workImageService;
    @Resource
    private ZjWorkGoodsService workGoodsService;
    @Resource
    private ZjWorkGoodsCodeService workGoodsCodeService;
    @Resource
    private ZjWorkReservationLogService workReservationLogService;
    @Resource
    private ZjWorkCancelService workCancelService;
    @Resource
    private ZjWorkStatementTemplateModuleService workStatementTemplateModuleService;
    @Resource
    private ZjWorkFinishOrderService workFinishOrderService;
    @Resource
    private ZjWorkFinishOrderTemplateService workFinishOrderTemplateService;
    @Resource
    private ZjWorkFinishOrderTemplateFieldValService workFinishOrderTemplateFieldValService;
    @Resource
    private ZjNetworkStrategyService networkStrategyService;
    @Resource
    private ZjWorkChangeEngineerService workChangeEngineerService;
    @Resource
    private ZjWorkReassignService workReassignService;
    @Resource
    private ZjNetworkEmpService networkEmpService;
    @Resource
    private WorkSlaUtilService workSlaUtilService;
    @Resource
    private ZjWorkEngineerSignService workEngineerSignService;
    @Resource
    private ZjWorkEngineerSignAnnexService workEngineerSignAnnexService;
    @Resource
    private ZjWorkTotalFeeFreezeService workTotalFeeFreezeService;
    @Resource
    private ZjFactoryOrderDeductionBillService factoryOrderDeductionBillService;
    @Resource
    private ViewNetworkEmpDetailService viewNetworkEmpDetailService;
    @Resource
    private ZjWorkFeeService workFeeService;
    @Resource
    private ZjWorkFeeDetailService workFeeDetailService;
    @Resource
    private ZjWorkSpareService workSpareService;
    @Resource
    private ZjWorkSpareReceiptService workSpareReceiptService;
    @Resource
    private ZjWorkSpareMaterialService workSpareMaterialService;
    @Resource
    private ConWorkOrderService conWorkOrderService;
    @Resource
    private ZjWorkHoubanYunRelationService workHoubanYunRelationService;

    @Resource
    private ZjWorkSlaConditionMapper zjWorkSlaConditionMapper;
    @Resource
    private ZjWorkSlaModuleMapper zjWorkSlaModuleMapper;

    // 获取服务商移动端待办数量
    @Override
    public NetworkEmpMobileToDoQtyVo getToDoQty(AccounLoginInfo loginInfo) {
        NetworkEmpMobileToDoQtyVo vo = new NetworkEmpMobileToDoQtyVo();
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        boolean networkManager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager()); // 是否服务商负责人
        // 服务商负责人
        if (networkManager) {
            QueryWrapper<ZjWorkDispatchNetwork> dispatchNetworkQueryWrapper = new QueryWrapper<>();
            dispatchNetworkQueryWrapper.select("id", "status")
                    .in("status", 1, 2, 4)
                    .eq("network_id", loginInfo.getNetworkId());
            List<ZjWorkDispatchNetwork> dispatchNetworks = workDispatchNetworkService.list(dispatchNetworkQueryWrapper);
            // 待接单
            vo.setWaitReceivingOrderQty(dispatchNetworks.stream().filter(f -> f.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_1).count());
            // 待指派工程师
            vo.setWaitDispatchOrderQty(dispatchNetworks.stream().filter(f -> f.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_2).count());
            // 服务中
            vo.setServiceOrderQty(dispatchNetworks.stream().filter(f -> f.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_4).count());
            QueryWrapper<ZjWorkDispatchEngineer> dispatchEngineerQueryWrapper = new QueryWrapper<>();
            dispatchEngineerQueryWrapper.select("is_reservation AS reservation", "is_sign_in AS signIn")
                    .eq("status", 2)
                    .eq("network_id", loginInfo.getNetworkId())
                    .eq("network_emp_id", loginInfo.getNetworkEmpId());
            List<ZjWorkDispatchEngineer> dispatchEngineerList = workDispatchEngineerService.list(dispatchEngineerQueryWrapper);
            vo.setWaitReservationQty(dispatchEngineerList.stream().filter(f -> !f.getReservation()).count());
            vo.setWaitSignInOrderQty(dispatchEngineerList.stream().filter(f -> !f.getSignIn()).count());
        } else {
            QueryWrapper<ZjWorkDispatchEngineer> dispatchEngineerQueryWrapper = new QueryWrapper<>();
            dispatchEngineerQueryWrapper.select("status", "is_reservation AS reservation", "is_sign_in AS signIn")
                    .eq("cust_acc_id", loginInfo.getCustAccId())
                    .in("status", 1, 2)
                    .eq("network_emp_id", loginInfo.getNetworkEmpId());
            if (null != loginInfo.getNetworkId() && loginInfo.getNetworkId() > 0) {
                dispatchEngineerQueryWrapper.eq("network_id", loginInfo.getNetworkId());
            }
            List<ZjWorkDispatchEngineer> dispatchEngineerList = workDispatchEngineerService.list(dispatchEngineerQueryWrapper);
            // 待接单
            vo.setWaitReceivingOrderQty(dispatchEngineerList.stream().filter(f -> f.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_1).count());
            vo.setWaitReservationQty(dispatchEngineerList.stream().filter(f -> f.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_2 && !f.getReservation()).count());
            vo.setWaitSignInOrderQty(dispatchEngineerList.stream().filter(f -> f.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_2 && !f.getSignIn()).count());
            // 服务中
            vo.setServiceOrderQty(dispatchEngineerList.stream().filter(f -> f.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_2).count());
        }
        QueryWrapper<ZjWorkOrder> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.select("id", "status", "is_end_order AS endOrder", "settlement_status", "suspend_status", "module_id", "is_assign_emp AS assignEmp", "gmt_create", "gmt_update");
            orderQueryWrapper.eq("cust_acc_id", loginInfo.getCustAccId());
            orderQueryWrapper.eq("network_id", loginInfo.getNetworkId());
        if (!networkManager) {
            orderQueryWrapper.eq("network_emp_id", loginInfo.getNetworkEmpId());
        }
        List<ZjWorkOrder> orderList = workOrderService.list(orderQueryWrapper);
        vo.setOrderSuspendQty(orderList.stream().filter(f -> f.getSuspendStatus() == 2).count());
        List<OrderSlaSelectVo> orderSlaSelectVos = orderList.stream().filter(f -> f.getStatus() == 3).map(order -> {
            return new OrderSlaSelectVo(order.getId(), order.getModuleId(), order.getStatus(), order.getAssignEmp(), order.getGmtCreate(), order.getGmtUpdate());
        }).toList();
        List<OrderSlaVo> slaVoList = workSlaUtilService.getOrderSlaInfo(orderSlaSelectVos);
        vo.setOverCallPhoneQty(slaVoList.stream().filter(f -> f.isNodeTimeout() && f.getType() == 5).count());
        vo.setOverUnreservation(slaVoList.stream().filter(f -> f.isNodeTimeout() && f.getType() == 6).count());
        vo.setOverUnSignIn(slaVoList.stream().filter(f -> f.isNodeTimeout() && f.getType() == 7).count());
        return vo;
    }

    // 获取侧边栏数据
    @Override
    public Object getSidebarData(AccounLoginInfo loginInfo) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        boolean networkManager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager()); // 是否服务商负责人
        long messageQty = 0;
        if (networkManager) {
            messageQty = workLeaveMessageService.getNetworkUnreadMessageQty(loginInfo.getCustAccId(), loginInfo.getNetworkId());
        } else {
            messageQty = workLeaveMessageService.getNetworkEmpUnReadMessageQty(loginInfo.getCustAccId(), loginInfo.getNetworkId(),loginInfo.getNetworkEmpId());
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("toBeExpectedToSettlementQty", new BigDecimal("0.0").add(BigDecimal.valueOf(Math.random() * 10000)).floatValue()); // todo 今日预计结算
        resultMap.put("todayFinishOrderQty", workOrderService.getTodayFinishOrderQty(loginInfo.getCustAccId(), loginInfo.getNetworkId(), networkManager? null : loginInfo.getNetworkEmpId())); // 今日完成单量
        resultMap.put("messageQty", messageQty); // 消息中心
        return resultMap;
    }

    // 获取工单合计
    @Override
    public Map<String, Object> getNetworkOrderStat(AccounLoginInfo loginInfo, NetworkOrderStatSelectVo selectVo) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        boolean networkManager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager()); // 是否服务商负责人
        Long custAccId = loginInfo.getCustAccId() == 0 ? null : loginInfo.getCustAccId();
        Long networkId = loginInfo.getNetworkId() == 0? null : loginInfo.getNetworkId();
        Long networkEmpId = networkManager? null : loginInfo.getNetworkEmpId();
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("totalOrderQty", workOrderService.getNetworkMobileTotalOrderQty(custAccId, networkId, networkEmpId, selectVo));
        resultMap.put("finishOrderQty", workOrderService.getNetworkMobileFinishOrderQty(custAccId, networkId, networkEmpId, selectVo));
        return resultMap;
    }

     // 获取服务商近七天的工单数
    @Override
    public Object getNetworkInSevenDaysOrder(AccounLoginInfo loginInfo) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        boolean networkManager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager()); // 是否服务商负责人
        Long networkId = null;
        Long networkEmpId = null;
        if (networkManager) {
            networkId = loginInfo.getNetworkId();
        } else {
            networkEmpId = loginInfo.getNetworkEmpId();
        }
        List<DateQtyVo> dateQtyVos = workOrderService.getNetworkInSevenDaysOrder(loginInfo.getCustAccId(), networkId, networkEmpId);
        return ZbDateUtil.getInDateRange(-7).stream().map(date -> {
            return new DateQtyVo(
                    date,
                    dateQtyVos.stream().filter(f -> Objects.equals(f.getDate(), date)).findFirst().map(DateQtyVo::getQty).orElse(0L)
            );
        }).sorted((s1, s2) -> s2.getDate().compareTo(s1.getDate()));
    }

    /**
     * 统计数据共同方法
     * @param dateStrList
     * @param todayCreateOrder
     * @param todayFinishOrder
     */
    private void getDateQtyVo(List<String> dateStrList, List<DateQtyVo> todayCreateOrder, List<DateQtyVo> todayFinishOrder) {
        dateStrList.forEach(t -> {
            if (todayCreateOrder.stream().noneMatch(f -> Objects.equals(f.getDate(), t))) {
                todayCreateOrder.add(new DateQtyVo(t, 0));
            }
            if (todayFinishOrder.stream().noneMatch(f -> Objects.equals(f.getDate(), t))) {
                todayFinishOrder.add(new DateQtyVo(t, 0));
            }
        });
    }

    // 获取排行榜数据
    @Override
    public Map<String, Object> getNetworkOrderScoreStat(AccounLoginInfo loginInfo, NetworkOrderStatSelectVo selectVo) {
        List<QtyVo> finishOrder = workOrderService.getNetworkFinishOrderScoreStat(loginInfo.getNetworkId(), selectVo);
        finishOrder = finishOrder.stream().filter(f -> f.getId() > 0).toList();
        List<Long> networkEmpIds = finishOrder.stream().map(QtyVo::getId).toList();
        List<ViewNetworkEmpAccount> empAccounts = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(networkEmpIds)) {
            empAccounts.addAll(viewNetworkEmpAccountService.getByIds(networkEmpIds.stream().distinct().toList()));
        }
        List<NetworkMobileEmpScoreVo> voList = finishOrder.stream().map(o -> {
            NetworkMobileEmpScoreVo vo = new NetworkMobileEmpScoreVo();
            BeanUtil.copyProperties(o, vo);
            ViewNetworkEmpAccount empAccount = empAccounts.stream().filter(f -> Objects.equals(f.getId(), o.getId())).findFirst().orElse(null);
            if (null != empAccount) {
                vo.setName(empAccount.getName());
                vo.setAvatar(empAccount.getAvatar());
            }
            return vo;
        }).toList();
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("finishOrder", voList.stream().sorted((s1, s2) -> s2.getQty().compareTo(s1.getQty())));
        return resultMap;
    }

    // 获取工单报表(工单类型占比)
    @Override
    public Map<String, Object> getNetworkOrderModuleStat(AccounLoginInfo loginInfo, NetworkOrderStatSelectVo selectVo) {
        Map<String, Object> resultMap = new HashMap<>();
        ZjNetworkEmpRelation networkEmpRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        boolean manager = null != networkEmpRelation && (networkEmpRelation.getManager() || networkEmpRelation.getSuperManager()); // 是否超管或负责人，默认否
        if (!manager) {
            selectVo.setNetworkEmpId(loginInfo.getNetworkEmpId());
        }
        List<QtyVo> voList = workOrderService.getNetworkOrderModuleStat(loginInfo.getNetworkId(), selectVo);
        List<Long> moduleIds = voList.stream().map(QtyVo::getId).toList();
        List<ZjWorkModule> workModuleList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(moduleIds)) {
            QueryWrapper<ZjWorkModule> moduleQueryWrapper = new QueryWrapper<>();
            moduleQueryWrapper.select("id", "name", "type");
            moduleQueryWrapper.in("id", voList.stream().map(QtyVo::getId).toList());
            workModuleList.addAll(workModuleService.list(moduleQueryWrapper));
        }
        voList.forEach(t -> {
            ZjWorkModule module = workModuleList.stream().filter(f -> Objects.equals(f.getId(), t.getId())).findFirst().orElse(null);
            if (null != module) {
                t.setName("【" + WorkConverter.moduleTypeConverter(module.getType()) + "】" + module.getName());
            }
        });
        resultMap.put("totalOrderQty", CollectionUtil.isNotEmpty(voList)? voList.stream().map(QtyVo::getQty).reduce(Integer::sum) : 0); // 总工单数量
        resultMap.put("orderModuleStat", voList);
        return resultMap;
    }

    // 获取工单报表(工单分析)
    @Override
    public Map<String, Object> getWeekOrderStat(AccounLoginInfo loginInfo) {
        Map<String, Object> resultMap = new HashMap<>();
        List<DateQtyVo> todayCreateOrder = new ArrayList<>();
        List<DateQtyVo> todayFinishOrder = new ArrayList<>();

        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        if (null != empRelation && (empRelation.getManager() || empRelation.getSuperManager())) {
            todayCreateOrder.addAll(workOrderService.getNetworkMobileWeekCreateOrderStat(loginInfo.getCustAccId(), loginInfo.getNetworkId(), loginInfo.getNetworkEmpId(), true));
            todayFinishOrder.addAll(workOrderService.getNetworkMobileWeekEndOrderStat(loginInfo.getCustAccId(), loginInfo.getNetworkId(), loginInfo.getNetworkEmpId(), true));
        } else {
            todayCreateOrder.addAll(workOrderService.getNetworkMobileWeekCreateOrderStat(loginInfo.getCustAccId(), loginInfo.getNetworkId(), loginInfo.getNetworkEmpId(), false));
            todayFinishOrder.addAll(workOrderService.getNetworkMobileWeekEndOrderStat(loginInfo.getCustAccId(), loginInfo.getNetworkId(), loginInfo.getNetworkEmpId(), false));
        }

        getDateQtyVo(ZbDateUtil.getCurrentWeekAllDate(), todayCreateOrder, todayFinishOrder);
        resultMap.put("todayCreateOrder", todayCreateOrder.stream().sorted((s, s1) -> s.getDate().compareTo(s1.getDate())));
        resultMap.put("todayFinishOrder", todayFinishOrder.stream().sorted((s, s1) -> s.getDate().compareTo(s1.getDate())));
        return resultMap;
    }

    // 获取服务商消息列表
    @Override
    public Map<String, Object> getNetworkOrderMessageList(AccounLoginInfo loginInfo, NetworkMobileOrderMessageListSelectVo selectVo) {
        PageUtil.setPageLimitMobile(selectVo);
        ZjNetworkEmpRelation networkEmpRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        boolean manager = null != networkEmpRelation && (networkEmpRelation.getManager() || networkEmpRelation.getSuperManager()); // 是否超管或负责人，默认否
        Long networkEmpId = null;
        Long networkId = loginInfo.getNetworkId();
        if (!manager) {
            networkEmpId = loginInfo.getNetworkEmpId();
        }
        long count = workOrderService.getNetworkMobileOrderMessageListCount(networkId, networkEmpId, selectVo);
        if (count <= 0) {
            return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), count, new ArrayList<>());
        }
        List<WorkOrderExtend> orderList = workOrderService.getNetworkMobileOrderMessageList(networkId, networkEmpId, selectVo);

        List<Long> moduleIds = orderList.stream().map(ZjWorkOrder::getModuleId).distinct().toList();
        List<Long> ids = orderList.stream().map(ZjWorkOrder::getId).toList();
        // 模块
        QueryWrapper<ZjWorkModule> moduleQueryWrapper = new QueryWrapper<>();
        moduleQueryWrapper.select("id", "name", "type");
        moduleQueryWrapper.in("id", moduleIds);
        List<ZjWorkModule> modules = workModuleService.list(moduleQueryWrapper);
        // 最新留言
        List<ZjWorkLeaveMessage> leaveMessages = workLeaveMessageService.getNetworkLastOneMesageByWorkIds(manager, ids);
        List<QtyVo> leaveMessageQtys = workLeaveMessageService.getNetworkNotReadQtyList(manager, ids);

        List<ZjWorkDispatchNetwork> dispatchNetworks = new ArrayList<>();
        List<ZjWorkDispatchEngineer> dispatchEngineers = new ArrayList<>();
        List<ViewNetworkEmpAccount> empAccountList = viewNetworkEmpAccountService.getByIds(orderList.stream().map(WorkOrderExtend::getNetworkEmpId).distinct().toList());
        if (manager) {
            dispatchNetworks.addAll(workDispatchNetworkService.getByNetworkIdAndWorkIds(loginInfo.getNetworkId(), ids));
        } else {
            dispatchEngineers.addAll(workDispatchEngineerService.getByNetworkEmpIdAndWorkIds(loginInfo.getNetworkId(), loginInfo.getNetworkEmpId(), ids));
        }
        List<NetworkOrderMessageListVo> voList = orderList.stream().map(o -> {
            NetworkOrderMessageListVo vo = new NetworkOrderMessageListVo();
            vo.setId(o.getId());
            vo.setWorkNo(o.getCode());
            vo.setUserName(o.getUserName());
            vo.setUserPhone(o.getUserPhone());
            modules.stream().filter(f -> Objects.equals(f.getId(), o.getModuleId())).findFirst().ifPresent(module -> {
                vo.setModule("【" + WorkConverter.moduleTypeConverter(module.getType()) + "】" + module.getName());
            });
            leaveMessages.stream().filter(f -> Objects.equals(f.getWorkId(), o.getId())).findFirst().ifPresent(leave -> {
                vo.setLeaveMessageTime(leave.getGmtCreate());
                vo.setLeaveMessage(leave.getContent());
//                vo.setLeaveAnnex(leave.getAnnex());
            });
            vo.setLeaveMessageQty(leaveMessageQtys.stream().filter(f -> Objects.equals(f.getId(), o.getId())).map(QtyVo::getQty).findFirst().orElse(0));
            if (manager) {
                vo.setStatus(dispatchNetworks.stream().filter(f -> Objects.equals(f.getWorkId(), o.getId())).map(ZjWorkDispatchNetwork::getStatus).findFirst().orElse(1));
            } else {
                vo.setStatus(dispatchEngineers.stream().filter(f -> Objects.equals(f.getWorkId(), o.getId())).map(ZjWorkDispatchEngineer::getStatus).findFirst().orElse(1));
            }
            empAccountList.stream().filter(f -> Objects.equals(f.getId(), o.getNetworkEmpId())).findFirst().map(ViewNetworkEmpAccount::getName).ifPresent(vo::setEngineer);
            return vo;
        }).toList();
        return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), count, voList);
    }

    // 更新未读留言
    @Override
    public void updateNetworkOrderNotReadMessage(AccounLoginInfo loginInfo, Long workId) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        // 判断是否为工程师
        boolean manager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager());
        if (manager) {
            ZjWorkOrder order = workOrderService.getById(workId);
            workLeaveMessageService.updateNetworkNotReadLeaveMessageByWorkId(workId, Objects.equals(loginInfo.getNetworkEmpId(), order.getNetworkEmpId()));
            return;
        }
        workLeaveMessageService.updateEngineerNotReadLeaveMessageByWorkId(workId);
    }

    // 根据工单ID获取留言列表
    @Override
    public Map<String, Object> getNetworkOrderMessage(AccounLoginInfo loginInfo, Long workId, PageUtil pageUtil) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        PageUtil.setPageLimit(pageUtil);
        List<ZjWorkLeaveMessage> messages = null;
        long totalCount = 0;
        if (null != empRelation && (empRelation.getManager() || empRelation.getSuperManager())) {
            messages = workLeaveMessageService.getNetworkWorkLeaveMessageList(loginInfo.getId(), workId, pageUtil);
            totalCount = workLeaveMessageService.getNetworkWorkLeaveMessageListCount(loginInfo.getId(), workId);
        } else {
            messages = workLeaveMessageService.getEngineerWorkLeaveMessageList(loginInfo.getId(), workId, pageUtil);
            totalCount = workLeaveMessageService.getEngineerWorkLeaveMessageListCount(loginInfo.getId(), workId);
        }
        List<Long> empIds = messages.stream().filter(f -> f.getEmpType() == 1 || f.getEmpType() == 2 || f.getEmpType() == 3).map(ZjWorkLeaveMessage::getEmpId).distinct().toList();
        List<Long> userIds = messages.stream().filter(f -> f.getEmpType() == 4).map(ZjWorkLeaveMessage::getEmpId).distinct().toList();
        List<ZjAccount> accountList = new ArrayList<>();
        List<ZjUser> userList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(empIds)) {
            accountList.addAll(accountService.getByIds(empIds));
        }
        List<ZjWorkLeaveMessageAnnex> messageAnnexList = workLeaveMessageAnnexService.getByWorkId(workId);
        if (CollectionUtil.isNotEmpty(userIds)) {
            QueryWrapper<ZjUser> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.select("id", "avatar");
            userList.addAll(userService.list(userQueryWrapper));
        }
        List<WorkLeaveMessageListVo> voList = messages.stream().map(m -> {
            WorkLeaveMessageListVo vo = new WorkLeaveMessageListVo();
            BeanUtil.copyProperties(m, vo);
            vo.setCreateTime(m.getGmtCreate());
            if (m.getEmpType() == 1 || m.getEmpType() == 2 || m.getEmpType() == 3) {
                accountList.stream().filter(f -> Objects.equals(f.getId(), m.getEmpId())).findFirst().map(ZjAccount::getAvatar).ifPresent(vo::setAvatar);
            } else {
                userList.stream().filter(f -> Objects.equals(f.getId(), m.getEmpId())).findFirst().map(ZjUser::getAvatar).ifPresent(vo::setAvatar);
            }
            vo.setAnnexs(messageAnnexList.stream().filter(f -> Objects.equals(f.getWorkLeaveMessageId(), m.getId())).map(ZjWorkLeaveMessageAnnex::getPath).toList());
            return vo;
        }).toList();
        return PageUtil.pageList(pageUtil.getPage(), pageUtil.getLimit(), totalCount, voList);
    }

    // 获取服务商工单列表状态数量
    @Override
    public NetworkOrderStatusQtyVo getNetworkOrderListStatusQty(AccounLoginInfo loginInfo, String keyword) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        if (null != empRelation && (empRelation.getManager() || empRelation.getSuperManager())) {
            return workDispatchNetworkService.getNetworkOrderListStatusQty(loginInfo.getCustAccId(), loginInfo.getNetworkId(), null);
        }
        // 工程师
        return workDispatchEngineerService.getNetworkOrderListStatusQty(loginInfo.getNetworkId(), loginInfo.getNetworkEmpId(), null);
    }

    // 获取服务商工单列表
    @Override
    public Map<String, Object> getNetworkOrderList(AccounLoginInfo loginInfo, NetworkMobileOrderListSelectVo selectVo) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        boolean manager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager());
        PageUtil.setPageLimitMobile(selectVo);
        // 在处理中状态的工单搜索待核销的工单
        if(selectVo.getStatus() != null && selectVo.getStatus() == 8){
            selectVo.setStatus(4);
        }
        // 管理员或服务商负责人
        if (manager) {
            long listCount = workDispatchNetworkService.getNetworkOrderListCount(loginInfo.getCustAccId(), loginInfo.getNetworkId(), selectVo);
            if (listCount <= 0) {
                return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), listCount, new ArrayList<>());
            }
            List<NetworkDispatchOrderListExtend> dispatchNetworkList = workDispatchNetworkService.getNetworkOrderList(loginInfo.getCustAccId(), loginInfo.getNetworkId(), selectVo);
            return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), listCount, getNetworkManagerOrderListData(loginInfo, dispatchNetworkList));
        }
        if (null != selectVo.getStatus()) {
            selectVo.setStatus(4 == selectVo.getStatus()? 2 : 5 == selectVo.getStatus()? 3 : 6 == selectVo.getStatus()? 4 : 7 == selectVo.getStatus()? 5 : selectVo.getStatus());
        }
        // 工程师
        long count = workDispatchEngineerService.getNetworkOrderListCount(loginInfo.getCustAccId(), loginInfo.getNetworkId(), loginInfo.getNetworkEmpId(), selectVo);
        if (count <= 0) {
            return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), count, new ArrayList<>());
        }
        List<NetworkEmpDispatchOrderListExtend> dispatchEngineers = workDispatchEngineerService.getNetworkEmpOrderList(loginInfo.getCustAccId(), loginInfo.getNetworkId(), loginInfo.getNetworkEmpId(), selectVo);
        return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), count, getNetworkEmpOrderListData(loginInfo, dispatchEngineers));
    }

    /**
     * 获取服务商管理员工单列表数据
     * @param loginInfo
     * @param dispatchNetworkList
     * @return
     */
    private List<NetworkManagerMobileOrderListVo> getNetworkManagerOrderListData(AccounLoginInfo loginInfo, List<NetworkDispatchOrderListExtend> dispatchNetworkList) {
        List<Long> workIdList = dispatchNetworkList.stream().map(ZjWorkDispatchNetwork::getWorkId).toList();
        // 查询派单工程师
        List<ZjWorkDispatchEngineer> dispatchEngineerList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(workIdList)) {
            QueryWrapper<ZjWorkDispatchEngineer> engineerQueryWrapper = new QueryWrapper<>();
            engineerQueryWrapper.select("id", "work_id", "network_emp_id", "dispatch_time", "is_reservation AS reservation", "reservation_date", "reservation_start_time", "reservation_end_time",
                            "is_sign_in AS signIn")
                    .between("status", 1, 5)
                    .in("work_id", workIdList);
            dispatchEngineerList.addAll(workDispatchEngineerService.list(engineerQueryWrapper));
        }
        List<Long> moduleIds = dispatchNetworkList.stream().map(NetworkDispatchOrderListExtend::getModuleId).distinct().toList();
        List<Long> workLevelIds = dispatchNetworkList.stream().map(NetworkDispatchOrderListExtend::getWorkLevelId).distinct().toList();
        // 工单模块
        List<ZjWorkModule> modules = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(moduleIds)) {
            QueryWrapper<ZjWorkModule> moduleQueryWrapper = new QueryWrapper<>();
            moduleQueryWrapper.select("id", "type", "name");
            moduleQueryWrapper.in("id", moduleIds);
            modules.addAll(workModuleService.list(moduleQueryWrapper));
        }
        // 工单等级
        List<ZjWorkLevel> levelList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(workLevelIds)) {
            QueryWrapper<ZjWorkLevel> workLevelQueryWrapper = new QueryWrapper<>();
            workLevelQueryWrapper.select("id", "name", "color");
            workLevelQueryWrapper.in("id", workLevelIds);
            levelList.addAll(workLevelService.list(workLevelQueryWrapper));
        }
        // 工单结单申请
        List<ZjWorkFinishOrder> finishOrders = workFinishOrderService.getApplyEndOrderByWorkIds(workIdList);
        // 工单客户
        List<ZjWorkUser> workUserList = workUserService.getByIds(workIdList);
        // 待审核的转单
        List<ZjWorkChangeEngineer> changeEngineers = workChangeEngineerService.getTransferOrderStatutWaitCheckStatus(loginInfo.getNetworkId(), workIdList);
        // 已申请改派服务待审核的工单
        List<ZjWorkReassign> workReassigns = workReassignService.getWaitCheckWorkReassignByNetworkIdAndWorkIds(loginInfo.getNetworkId(), workIdList);
        // 服务商已申请取消工单待审核
        List<ZjWorkCancel> workCancels = workCancelService.getWaitCheckCancelOrderByNetworkIdAndWorkIds(loginInfo.getNetworkId(), workIdList);

        ZjWorkLevel level = null;
        ZjWorkUser workUser = null;
        ZjWorkDispatchEngineer workDispatchEngineer = null;
        ZjWorkChangeEngineer changeEngineer = null;
        List<NetworkManagerMobileOrderListVo> managerMobileOrderListVos = new ArrayList<>();
        NetworkManagerMobileOrderListVo vo = null;
        for (NetworkDispatchOrderListExtend mo : dispatchNetworkList) {
            vo = new NetworkManagerMobileOrderListVo();
            BeanUtil.copyProperties(mo, vo);
            vo.setId(mo.getWorkId());
            vo.setServiceDispatchTime(mo.getDispatchTime());
            vo.setModule(modules.stream().filter(f -> Objects.equals(f.getId(), mo.getModuleId())).map(m -> {
                return "【" + WorkConverter.moduleTypeConverter(m.getType()) + "】" + m.getName();
            }).findFirst().orElse(""));
            level = levelList.stream().filter(f -> Objects.equals(f.getId(), mo.getWorkLevelId())).findFirst().orElse(null);
            if (null != level) {
                vo.setOrderLevel(level.getName());
                vo.setOrderLevelColor(level.getColor());
            }
            vo.setWaitSettlementOrder(mo.getSettlementStatus() == WorkConstant.WORK_SETTLEMENT_STATUS_3);
            workUser = workUserList.stream().filter(f -> Objects.equals(f.getId(), mo.getWorkId())).findFirst().orElse(null);
            if (null != workUser) {
                vo.setUserName(workUser.getName());
                vo.setUserPhone(workUser.getPhone());
                vo.setProvince(workUser.getProvince());
                vo.setCity(workUser.getCity());
                vo.setArea(workUser.getArea());
                vo.setTown(workUser.getTown());
                vo.setAddress(workUser.getAddress());
            }
            vo.setApplyfinishTime(finishOrders.stream().filter(f -> Objects.equals(f.getWorkId(), mo.getWorkId())).map(ZjWorkFinishOrder::getGmtCreate).findFirst().orElse(null));
            vo.setEndOrderTime(mo.getEndTime());
            vo.setReceivableMoney(new BigDecimal("0.0")); // todo 应收金额
            vo.setActualReceivedMoney(new BigDecimal("0.0")); // todo 实收金额

            workDispatchEngineer = dispatchEngineerList.stream().filter(f -> Objects.equals(f.getWorkId(), mo.getWorkId())).findFirst().orElse(null);
            if (null != workDispatchEngineer) {
                vo.setEngineer(Objects.equals(workDispatchEngineer.getNetworkEmpId(), loginInfo.getNetworkEmpId()));
                vo.setNetworkDispatchTime(ZbDateConvertUtil.dateStrToDate(workDispatchEngineer.getDispatchTime()));
                vo.setReservation(workDispatchEngineer.getReservation());
                vo.setReservationDate(ZbDateConvertUtil.dateStrToDate(workDispatchEngineer.getReservationDate()));
                vo.setReservationStartTime(ZbDateConvertUtil.dateStrToDate(workDispatchEngineer.getReservationStartTime()));
                vo.setReservationEndTime(ZbDateConvertUtil.dateStrToDate(workDispatchEngineer.getReservationEndTime()));
                vo.setSignIn(workDispatchEngineer.getSignIn());
            }
            changeEngineer = changeEngineers.stream().filter(f -> Objects.equals(f.getWorkId(), mo.getWorkId())).findFirst().orElse(null);
            if (null != changeEngineer) {
                vo.setWaitCheckOrder(Boolean.TRUE);
                vo.setApplyType(1);
                vo.setApplyEmp(changeEngineer.getApplyNetworkEmp());
                vo.setApplyTime(changeEngineer.getGmtCreate());
            }
            if (CollectionUtil.isNotEmpty(workCancels)) {
                vo.setHasNetworkApplyOrderWaitCheck(workCancels.stream().anyMatch(f -> Objects.equals(f.getWorkId(), mo.getWorkId())));
                vo.setHasNetworkApplyOrderWaitCheckType(1);
            } else {
                vo.setHasNetworkApplyOrderWaitCheck(workReassigns.stream().anyMatch(f -> Objects.equals(f.getWorkId(), mo.getWorkId())));
                vo.setHasNetworkApplyOrderWaitCheckType(2);
            }
            vo.setApplyChangeNetworkWaitCheckOrder(workReassigns.stream().anyMatch(f -> Objects.equals(f.getWorkId(), mo.getWorkId())));
            // 是否暂挂
            ZjWorkOrder workOrder = workOrderService.getById(mo.getWorkId());
            vo.setIsPause(workOrder.getIsPause());
            managerMobileOrderListVos.add(vo);
        }
        return managerMobileOrderListVos;
    }

    /**
     * 获取工程师工单列表
     * @return
     */
    private List<NetworkMobileOrderListVo> getNetworkEmpOrderListData(AccounLoginInfo loginInfo, List<NetworkEmpDispatchOrderListExtend> dispatchEngineers) {
        List<Long> moduleIds = dispatchEngineers.stream().map(NetworkEmpDispatchOrderListExtend::getModuleId).distinct().toList();
        List<Long> workLevelIds = dispatchEngineers.stream().map(NetworkEmpDispatchOrderListExtend::getWorkLevelId).distinct().toList();
        List<Long> workIdList = dispatchEngineers.stream().map(ZjWorkDispatchEngineer::getWorkId).toList();
        // 工单模块
        List<ZjWorkModule> modules = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(moduleIds)) {
            QueryWrapper<ZjWorkModule> moduleQueryWrapper = new QueryWrapper<>();
            moduleQueryWrapper.select("id", "type", "name");
            moduleQueryWrapper.in("id", moduleIds);
            modules.addAll(workModuleService.list(moduleQueryWrapper));
        }
        // 工单等级
        List<ZjWorkLevel> levelList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(workLevelIds)) {
            QueryWrapper<ZjWorkLevel> workLevelQueryWrapper = new QueryWrapper<>();
            workLevelQueryWrapper.select("id", "name", "color");
            workLevelQueryWrapper.in("id", workLevelIds);
            levelList.addAll(workLevelService.list(workLevelQueryWrapper));
        }
        // 工单结单申请
        List<ZjWorkFinishOrder> finishOrders = workFinishOrderService.getApplyEndOrderByWorkIds(workIdList);
        // 工单客户
        List<ZjWorkUser> workUserList = workUserService.getByIds(workIdList);
        // 查询工程师已申请转单的工单
        List<ZjWorkChangeEngineer> changeEngineers = workChangeEngineerService.getWaitCheckTransferOrderApplyByNetworkEmpIdAndWorkIds(loginInfo.getNetworkEmpId(), workIdList);
        List<NetworkMobileOrderListVo> voList = new ArrayList<>();
        NetworkMobileOrderListVo vo = null;
        ZjWorkLevel level = null;
        ZjWorkUser workUser = null;
        for (NetworkEmpDispatchOrderListExtend engineer : dispatchEngineers) {
            vo = new NetworkMobileOrderListVo();
            BeanUtil.copyProperties(engineer, vo);
            vo.setId(engineer.getWorkId());
            vo.setModule(modules.stream().filter(f -> Objects.equals(f.getId(), engineer.getModuleId())).map(mo -> {
                return "【" + WorkConverter.moduleTypeConverter(mo.getType()) + "】" + mo.getName();
            }).findFirst().orElse(""));
            level = levelList.stream().filter(f -> Objects.equals(f.getId(), engineer.getWorkLevelId())).findFirst().orElse(null);
            if (null != level) {
                vo.setOrderLevel(level.getName());
                vo.setOrderLevelColor(level.getColor());
            }
            vo.setWaitSettlementOrder(engineer.getSettlementStatus() == WorkConstant.WORK_SETTLEMENT_STATUS_3);
            workUser = workUserList.stream().filter(f -> Objects.equals(f.getId(), engineer.getWorkId())).findFirst().orElse(null);
            if (null != workUser) {
                vo.setUserName(workUser.getName());
                vo.setUserPhone(workUser.getPhone());
                vo.setProvince(workUser.getProvince());
                vo.setCity(workUser.getCity());
                vo.setArea(workUser.getArea());
                vo.setTown(workUser.getTown());
                vo.setAddress(workUser.getAddress());
            }
            vo.setApplyfinishTime(finishOrders.stream().filter(f -> Objects.equals(f.getWorkId(), engineer.getWorkId())).map(ZjWorkFinishOrder::getGmtCreate).findFirst().orElse(null));
            vo.setEndOrderTime(engineer.getEndTime());
            vo.setReceivableMoney(new BigDecimal("0.0")); // todo 应收金额
            vo.setActualReceivedMoney(new BigDecimal("0.0")); // todo 实收金额
            vo.setHasEngineerApplyOrderWaitCheckType(1);
            vo.setHasEngineerApplyOrderWaitCheck(changeEngineers.stream().anyMatch(f -> Objects.equals(engineer.getWorkId(), f.getWorkId())));
            // 是否暂挂
            ZjWorkOrder workOrder = workOrderService.getById(engineer.getWorkId());
            vo.setIsPause(workOrder.getIsPause());
            voList.add(vo);
        }
        return voList;
    }

    // 服务商确认接单
    @Override
    @Transactional
    public void networkSureReceiveOrder(AccounLoginInfo loginInfo, Long workId, Integer expressCompany, String expressNbr) {
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.isTrue(null != order, "工单数据不存在");
        Assert.isFalse(order.getStatus() == WorkConstant.WORK_STATUS_1, "当前工单未派单服务商，不可跨流程接单");
        Assert.isFalse(order.getStatus() == WorkConstant.WORK_STATUS_4, "当前服务工单已完工，不可重复接单流程");
        Assert.isFalse(order.getStatus() == WorkConstant.WORK_STATUS_5, "当前服务工单已取消，禁止操作接单流程");

        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        Assert.isTrue(null != empRelation, "暂不支持非服务商人员接单操作，请加入服务商进行");
        boolean manager = empRelation.getManager() || empRelation.getSuperManager();

        List<WorkLogVo> networkLogs = new ArrayList<>();
        ZjWorkOrder workOrder = new ZjWorkOrder();
        workOrder.setId(workId);
        workOrder.setNewAdvance(order.getNewAdvance() +1);
        workOrder.setUpdateEmpId(loginInfo.getId());
        workOrder.setUpdateEmp(loginInfo.getName());
        workOrder.setExpressCompany(expressCompany);
        workOrder.setExpressNbr(expressNbr);

        // 服务商确认接单
        if (order.getStatus() == WorkConstant.WORK_STATUS_2) {
            Assert.isTrue(manager, "您不是当前服务商的负责人或管理员，没有权限接单");
            ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(workId, loginInfo.getNetworkId());
            Assert.isTrue(null != dispatchNetwork, "当前工单不属于您的服务工单，不允许接单操作");
            Assert.isTrue(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_1, "当前工单已接单，不允许重复接单");

            ZjWorkDispatchNetwork newDispatchNetwork = new ZjWorkDispatchNetwork();
            newDispatchNetwork.setId(dispatchNetwork.getId());
            newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_2);
            newDispatchNetwork.setReceivingOrderTime(new Date());
            workDispatchNetworkService.updateById(newDispatchNetwork);
            networkLogs.add(new WorkLogVo(loginInfo, workId, "服务商已确认接单", "待派工"));
            workOrder.setStatus(WorkConstant.WORK_STATUS_3);
        }
        // 普通工程师确认接单
        if (order.getStatus() == WorkConstant.WORK_STATUS_3){
            ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(workId, loginInfo.getNetworkId(), loginInfo.getNetworkEmpId());
            Assert.isTrue(null != dispatchEngineer, "当前工单不属于您的服务工单，不允许接单操作");
            Assert.isTrue(dispatchEngineer.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单已接单，不允许重复接单");

            ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(workId, order.getNetworkId());
            ZjWorkDispatchNetwork newDispatchNetwork = new ZjWorkDispatchNetwork();
            newDispatchNetwork.setId(dispatchNetwork.getId());
            newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_4);
            workDispatchNetworkService.updateById(newDispatchNetwork);
            workDispatchEngineerService.saveEngineerSureReceiveOrder(dispatchEngineer.getId());
            networkLogs.add(new WorkLogVo(loginInfo, workId, "工程师已确认接单",  "待预约服务时间"));
        }
        workOrderService.updateById(workOrder);
        WorkServiceLog.saveNetwork(networkLogs);
    }

    // 服务商拒绝接单
    @Override
    public void networkRefuseReceiveOrder(AccounLoginInfo loginInfo, Long workId, RemarkVo remarkVo) {
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.isTrue(null != order, "工单数据不存在");
        Assert.isFalse(order.getStatus() == WorkConstant.WORK_STATUS_1, "当前工单未派单服务商，不可跨流程拒绝接单");
        Assert.isFalse(order.getStatus() == WorkConstant.WORK_STATUS_4, "当前服务工单已完工，不可重复操作拒绝接单流程");
        Assert.isFalse(order.getStatus() == WorkConstant.WORK_STATUS_5, "当前服务工单已取消，禁止操作拒绝接单流程");
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        Assert.isTrue(null != empRelation, "您不属于任何服务商人员，禁止此操作");

        ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(workId, loginInfo.getNetworkId());
        Assert.isTrue(null != dispatchNetwork, "当前工单不属于您的服务工单，不允许拒绝接单操作");
        Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_9, "当前工单【已改派】，不允许重复操作");
        Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_8, "当前工单您已拒绝接单，不允许重复操作");
        Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_6, "当前工单【已完成】，不允许重复操作");
        Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_7, "当前工单【已取消】，不允许重复操作");

        ZjWorkOrder workOrder = new ZjWorkOrder();
        workOrder.setId(workId);
        workOrder.setUpdateEmpId(loginInfo.getId());
        workOrder.setUpdateEmp(loginInfo.getName());
        workOrder.setNewAdvance(order.getNewAdvance() +1);

        List<WorkLogVo> networkLogs = new ArrayList<>();
        ZjWorkDispatchNetwork newDispatchNetwork = new ZjWorkDispatchNetwork();
        newDispatchNetwork.setId(dispatchNetwork.getId());
        boolean manager = empRelation.getManager() || empRelation.getSuperManager();
        // 服务商拒绝接单
        if (order.getStatus() == WorkConstant.WORK_STATUS_2) {
            Assert.isTrue(manager, "您不是当前服务商的负责人或管理员，没有权限拒绝接单");

            newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_8);
            newDispatchNetwork.setRemark(StringUtils.isBlank(remarkVo.getRemark())? "" : remarkVo.getRemark());

            networkLogs.add(new WorkLogVo(loginInfo, workId, "服务商已拒绝接单",
                    "服务商已拒绝接单，等待工单客服重新派单服务商" + (StringUtils.isNotBlank(remarkVo.getRemark())? "；备注：" + remarkVo.getRemark() : "")));

            workOrder.setNetworkId(0L);
            workOrder.setStatus(WorkConstant.WORK_STATUS_1);
            // 清除派单到服务商时间
            workDetailService.updateDispatchTimeById(workId);
        }
        // 工程师拒绝接单
        if (order.getStatus() == WorkConstant.WORK_STATUS_3) {
            ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(workId, loginInfo.getNetworkId(), loginInfo.getNetworkEmpId());
            Assert.isTrue(null != dispatchEngineer, "当前工单不属于您的服务工单，不允许拒绝接单操作");
            Assert.isTrue(dispatchEngineer.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单处于非 [待接单] 流程，禁止重复操作");

            workDispatchEngineerService.saveEngineerRefuseReceiveOrder(dispatchEngineer.getId(), remarkVo.getRemark());
            networkLogs.add(new WorkLogVo(loginInfo, workId, "工程师已拒绝接单",
                    "工程师已拒绝接单，等待服务商重新派工" + (StringUtils.isNotBlank(remarkVo.getRemark()) ? "；备注：" + remarkVo.getRemark() : "")));

            newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_2);
            workOrder.setNetworkEmpId(0L);
        }
        workDispatchNetworkService.updateById(newDispatchNetwork);
        workOrderService.updateById(workOrder);
        WorkServiceLog.saveNetwork(networkLogs);
    }

    // 服务商派工
    @Override
    @Transactional
    public void networkDispatchEngineer(AccounLoginInfo loginInfo, Long workId, NetworkMobileDispatchEngineerVo dispatchEngineerVo) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        Assert.notNull(empRelation, "您不属于任何服务商人员，禁止派工操作");
        boolean manager = empRelation.getManager() || empRelation.getSuperManager();
        Assert.isTrue(manager, "您不是服务商负责人或超管，没有派工权限！");

        ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(workId, loginInfo.getNetworkId());
        Assert.notNull(dispatchNetwork, "当前工单不属于您的服务工单，禁止派工操作");
        Assert.isTrue(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_2,
                dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_1? "当前工单服务商未确认接单，无法派工" :
                dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_3? "当前工单已派工，不允许重复派工" :
                dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_4? "当前工单已在处理中，禁止重复派工操作" : "当前工单流程已结束或工单已改派，禁止重复派工操作"
        );

        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.notNull(order, "服务工单不存在");
        Assert.isTrue(order.getStatus() == WorkConstant.WORK_STATUS_3,
                order.getStatus() == WorkConstant.WORK_STATUS_1 ? "当前服务工单未派单，不可跨流程派工" :
                        order.getStatus() == WorkConstant.WORK_STATUS_2 ? "当前服务工单派单的服务商未确认接单，不可跨流程派工" :
                                order.getStatus() == WorkConstant.WORK_STATUS_4 ? "当前服务工单已完工，禁止重复派工" : "当前服务工单已取消，禁止重复派工"
        );
        // 是否派工给自己的工单
        boolean dispatchOrderToMe = Objects.equals(loginInfo.getNetworkEmpId(), dispatchEngineerVo.getEngineerManagerId());
        // 工程师接单策略
        Boolean engineerAutoSureReceiveOrder = networkEmpService.isAutoSureReceiveOrderById(dispatchEngineerVo.getEngineerManagerId());
        List<WorkLogVo> networkLogs = new ArrayList<>();
        networkLogs.add(new WorkLogVo(loginInfo, workId, "服务商派单工程师", "已派单工程师，待工程师接单"));

        ZjWorkDispatchEngineer dispatchEngineer2 = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(workId, loginInfo.getNetworkId(), dispatchEngineerVo.getEngineerManagerId());
        ZjWorkDispatchEngineer dispatchEngineer = new ZjWorkDispatchEngineer();
        dispatchEngineer.setCustAccId(loginInfo.getCustAccId());
        dispatchEngineer.setWorkId(workId);
        dispatchEngineer.setNetworkId(loginInfo.getNetworkId());
        dispatchEngineer.setNetworkEmpId(dispatchEngineerVo.getEngineerManagerId());
        dispatchEngineer.setStatus(dispatchOrderToMe || engineerAutoSureReceiveOrder? WorkConstant.DISPATCH_ENGINEER_STATUS_2 : WorkConstant.DISPATCH_ENGINEER_STATUS_1);
        dispatchEngineer.setReceivingOrderTime(dispatchOrderToMe || engineerAutoSureReceiveOrder? ZbDateConvertUtil.dateToDateStr(new Date()) : "");
        dispatchEngineer.setDispatchTime(ZbDateConvertUtil.dateToDateStr(new Date()));
        dispatchEngineer.setDispatchRemark(dispatchEngineerVo.getRemark());
        dispatchEngineer.setReservation(false);
        dispatchEngineer.setReservationDate("");
        dispatchEngineer.setReservationStartTime("");
        dispatchEngineer.setReservationEndTime("");
        dispatchEngineer.setNetworkEmpFinishTime("");
        dispatchEngineer.setRemark("");
        dispatchEngineer.setCallPhoneQty(0);
        dispatchEngineer.setCallPhoneTime("");
        dispatchEngineer.setWriteCallPhoneResult(false);
        dispatchEngineer.setSignIn(false);
        if (null == dispatchEngineer2) {
            dispatchEngineer.setId(IdWorker.getId());
            workDispatchEngineerService.save(dispatchEngineer);
        } else {
            dispatchEngineer.setId(dispatchEngineer2.getId());
            workDispatchEngineerService.updateById(dispatchEngineer);
        }
        ZjWorkOrder workOrder = new ZjWorkOrder();
        workOrder.setId(workId);
        workOrder.setNewAdvance(order.getNewAdvance() +1);
        workOrder.setNetworkEmpId(dispatchEngineerVo.getEngineerManagerId());

        ZjWorkDispatchNetwork newDispatchNetwork = new ZjWorkDispatchNetwork();
        newDispatchNetwork.setId(dispatchNetwork.getId());
        newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_3);

        if (dispatchOrderToMe || engineerAutoSureReceiveOrder) {
            newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_4);
            ViewNetworkEmpAccount networkEmpAccount = viewNetworkEmpAccountService.getById(dispatchEngineerVo.getEngineerManagerId());
            networkLogs.add(new WorkLogVo(loginInfo.getCustAccId(), networkEmpAccount.getName(), workId, "工程师确认接单", "工程师已确认接单，等待工程师预约服务时间"));
        }
        workDispatchEngineerCooperateService.save(loginInfo.getCustAccId(), workId, dispatchEngineer.getId(), dispatchEngineerVo.getEngineerCooperateIds());
        workOrderService.updateById(workOrder);
        workDispatchNetworkService.updateById(newDispatchNetwork);
        WorkServiceLog.saveNetwork(networkLogs);
    }

    // 服务商申请取消工单
    @Override
    @Transactional
    public void networkApplyCancelOrder(AccounLoginInfo loginInfo, Long workId, String remark) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        Assert.notNull(empRelation, "您不属于任何服务商人员，禁止取消工单");
        Assert.isTrue(empRelation.getManager() || empRelation.getSuperManager(), "您不是服务商负责人或超管，没有取消工单的申请权限！");

        ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(workId, loginInfo.getNetworkId());
        Assert.notNull(dispatchNetwork, "当前工单不属于您的服务工单，您没有取消工单的权限");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_9, "当前工单已改派服务商，禁止申请取消工单");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_8, "当前工单已被服务商拒绝接单，禁止申请取消工单");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_6 || dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_7, "当前工单流程已结束，禁止申请取消工单");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_5, "当前工单正在待结单流程，禁止申请取消工单");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_1, "当前工单未确认接单，不允许申请取消工单");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_3, "当前工单已派工，不允许申请取消工单");
        ZjWorkOrder order = workOrderService.getById(workId);

        Assert.notNull(order, "服务工单不存在");
        Assert.isTrue(order.getStatus() == WorkConstant.WORK_STATUS_3,
                order.getStatus() == WorkConstant.WORK_STATUS_1 ? "当前服务工单未派单，不允许操作取消工单申请" :
                        order.getStatus() == WorkConstant.WORK_STATUS_2 ? "当前服务工单派单的服务商未确认接单，不可跨流程取消工单" :
                                order.getStatus() == WorkConstant.WORK_STATUS_4 ? "当前服务工单已完工，禁止取消工单" : "当前服务工单已取消，禁止重复取消工单"
        );
        // 判断工单是否已派工
        Assert.isTrue(null == order.getNetworkEmpId() || order.getNetworkEmpId() == 0, "当前工单已派工，无法申请取消工单");

        ZjWorkDetail workDetail = workDetailService.getById(workId);
        Assert.isFalse(workDetail.getCancelOrderApply(), "当前工单已申请取消工单，待审核中，不允许重复申请");
        Assert.isFalse(workDetail.getEndOrderApply(), "当前工单已申请结单，待审核中，不允许再申请取消");
        Assert.isFalse(workDetail.getChangeNetworkApply(), "当前工单已申请改派服务商，待审核中，不允许再申请取消");
        Assert.isTrue(workDetail.getNoReviewApplyWorkSpareNum() <= 0, "当前工单存在未审核备件，不允许申请取消工单");
        Assert.isTrue(workDetail.getNoReviewApplyWorkFeeNum() <= 0, "当前工单存在未审核服务费用项，不允许申请取消工单");

        // 自动审核取消工单申请策略
        ZjNetworkStrategy networkStrategy = networkStrategyService.getById(order.getNetworkId());
        boolean autoCheckCancelOrder = null != networkStrategy && networkStrategy.getAutoCheckCancelOrder();
        List<WorkLogVo> networkLogs = new ArrayList<>();
        networkLogs.add(new WorkLogVo(loginInfo, workId, "服务商申请取消工单", "待审核" + (StringUtils.isNotBlank(remark)? "；备注：" + remark: "")));

        ZjWorkCancel cancel = new ZjWorkCancel();
        cancel.setId(IdWorker.getId());
        cancel.setCustAccId(loginInfo.getCustAccId());
        cancel.setWorkId(workId);
        cancel.setNetworkId(loginInfo.getNetworkId());
        cancel.setApplyEmpType(2);
        cancel.setApplyEmpId(loginInfo.getId());
        cancel.setApplyEmp(loginInfo.getName());
        cancel.setApplyRemark(remark);

        ZjWorkOrder workOrder = new ZjWorkOrder();
        workOrder.setId(workId);
        workOrder.setUpdateEmpId(loginInfo.getId());
        workOrder.setUpdateEmp(loginInfo.getName());

        ZjWorkDetail detail = new ZjWorkDetail();
        detail.setId(workId);
        detail.setCancelOrderApply(!autoCheckCancelOrder);

        cancel.setReviewEmpId(0L);
        cancel.setReviewEmp("");
        cancel.setReviewRemark("");
        if (autoCheckCancelOrder) {
            cancel.setStatus(WorkConstant.WORK_CANCEL_STATUS_2);
            cancel.setReviewTime(new Date());

            workOrder.setNewAdvance(order.getNewAdvance() +1);
            workOrder.setStatus(WorkConstant.WORK_STATUS_5);
            workOrder.setCancelTime(new Date());

            ZjWorkDispatchNetwork newDispatchNetwork = new ZjWorkDispatchNetwork();
            newDispatchNetwork.setId(dispatchNetwork.getId());
            newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_7);
            workDispatchNetworkService.updateById(newDispatchNetwork);

            networkLogs.add(new WorkLogVo(loginInfo.getCustAccId(), "系统", workId,"系统自动审核取消工单", "审核通过"));
        } else {
            cancel.setStatus(WorkConstant.WORK_CANCEL_STATUS_1);
            workOrder.setWaitCopeEvent(order.getWaitCopeEvent() +1);
        }
        workCancelService.save(cancel);
        workOrderService.updateById(workOrder);
        workDetailService.updateById(detail);
        WorkServiceLog.saveNetwork(networkLogs);
    }

    // 获取结单模板及字段
    @Override
    public List<OrderStatementTemplateVo> getFinishOrderTemplateField(AccounLoginInfo loginInfo, Long workId) {
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.isTrue(null != order, "工单数据不存在");
        List<OrderStatementTemplateVo> templateVoList = workStatementTemplateModuleService.getFinishOrderTemplateFieldByModuleId(order.getModuleId());
        // 判断是否电信客户，如果是电信客户，则必填
        if (StringUtils.isNotBlank(order.getTeleCustomProIdenCode())) {
            for (OrderStatementTemplateVo templateVo : templateVoList) {
                // 判断指定结单模板
                if (Objects.equals(HoubanYunOrder.getcInstallFinishTemplateId1(), templateVo.getId()) ||
                        Objects.equals(HoubanYunOrder.getcUpdateFinishTemplateId1(), templateVo.getId())) {
                // 判断是否电信客户的字段
                    templateVo.getTemplateFieldVos().stream().filter(f -> Objects.equals(HoubanYunOrder.getcInstallFinishTemplateFieldId2(), f.getId()) ||
                            Objects.equals(HoubanYunOrder.getcUpdateFinishTemplateFieldId7(), f.getId())).toList().forEach(t1 -> {
                        t1.setRequired(true);
                    });
                }
            }
        }
        return templateVoList;
    }

    // 根据工单ID获取服务商信息
    @Override
    public NetworkMobileApplyStatementOrderInfoVo getNetworkStatement(Long workId) {
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.notNull(order, "服务商工单参数[ " + workId + " ]的数据不存在");
        ZjWorkModule module = workModuleService.getById(order.getModuleId());
        ZjWorkUser workUser = workUserService.getById(workId);
        ZjWorkDetail workDetail = workDetailService.getById(workId);

        NetworkMobileApplyStatementOrderInfoVo vo = new NetworkMobileApplyStatementOrderInfoVo();
        vo.setWorkNo(order.getCode());
        vo.setCreateTime(order.getGmtCreate());
        vo.setModule("【" + WorkConverter.moduleTypeConverter(module.getType()) + "】" + module.getName());
        vo.setModuleId(module.getId());
        vo.setUsername(workUser.getName());
        vo.setUserPhone(workUser.getPhone());
        vo.setContent(workDetail.getContent());
        vo.setTeleCustomProIdenCode(order.getTeleCustomProIdenCode());
        vo.setEnableStatementVerifCode(module.getEnableStatementVerifCode());
        vo.setLekaiOrder(workHoubanYunRelationService.isLaikaiOrder(workId));
        return vo;
    }

    // 根据工单ID获取结单核销码
    @Override
    public void getStatementWriteOffCode(AccounLoginInfo loginInfo, Long workId) throws SMSException {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        Assert.isTrue(null != empRelation, "您不属于任何服务商人员，禁止结单操作");

        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.notNull(order, "工单数据不存在");
        Assert.isTrue(Objects.equals(loginInfo.getNetworkEmpId(), order.getNetworkEmpId()), "您不是当前工单的工程师负责人，没有申请结单的权限！");
        Assert.isTrue(order.getStatus() == WorkConstant.WORK_STATUS_3,
                order.getStatus() == WorkConstant.WORK_STATUS_1? "当前服务工单未派单，禁止操作结单申请" :
                        order.getStatus() == WorkConstant.WORK_STATUS_2? "当前服务工单派单的服务商未确认接单，禁止操作结单申请" :
                                order.getStatus() == WorkConstant.WORK_STATUS_4? "当前服务工单已完工，禁止重复操作结单申请" : "当前服务工单已取消，禁止重复操作结单申请"
        );
        // 判断是否为工程师
        boolean manager = empRelation.getManager() || empRelation.getSuperManager();
        if (!manager) {
            // 校验工单是否转单或转单待审核
            boolean hasWaitOrder = workChangeEngineerService.isApplyChangeEngineerWaitCheck(workId);
            Assert.isFalse(hasWaitOrder, "当前工单已申请转单待审核中，禁止操作");
        }
        ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(order.getId(), order.getNetworkId(), loginInfo.getNetworkEmpId());
        ZjWorkModule module = workModuleService.getById(order.getModuleId());
        if (module.getCallPhoneType() == 1) {
            // 查询是否拨打电话
            Assert.isTrue(dispatchEngineer.getCallPhoneQty() > 0, "当前工单已开启必须拨打电话后才能执行后面的操作流程，您当前未拨打过电话，请拨打电话后再操作");
        }
        // 判断是否预约
        if (module.getReservationTimeType() != 1) {
            Assert.isTrue(dispatchEngineer.getReservation(), "当前您未预约，无法获取结单核销码！");
        }
        ZjWorkDetail workDetail = workDetailService.getById(order.getId());
        Assert.isFalse(workDetail.getCancelOrderApply(), "当前工单已申请取消工单，待审核中，不允许申请结单");
        Assert.isFalse(workDetail.getEndOrderApply(), "当前工单已申请结单，待审核中，不允许重复申请");
        Assert.isFalse(workDetail.getChangeNetworkApply(), "当前工单已申请改派服务商，待审核中，不允许申请结单");
        Assert.isTrue(workDetail.getNoReviewApplyWorkSpareNum() <= 0, "当前工单存在未审核备件，不允许申请结单");
        Assert.isTrue(workDetail.getNoReviewApplyWorkFeeNum() <= 0, "当前工单存在未审核服务费用项，不允许申请结单");
        // 判断是乐开客户的，都无需发送核销码
        if (workHoubanYunRelationService.isLaikaiOrder(workId)) {
            return;
        }
        conWorkOrderService.getStatementWriteOffCode(loginInfo, workId);
    }

    // 服务工程师申请结单
    @Override
    @Transactional
    public void networkApplyFinishOrder(AccounLoginInfo loginInfo, Long workId, NetworkMobileStatementVo statementVo) throws SMSException {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        Assert.isTrue(null != empRelation, "您不是该服务商的工程师，无法操作结单");

        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.notNull(order, "系统中没有此工单，无法申请结单！");
        Assert.isTrue(Objects.equals(loginInfo.getNetworkEmpId(), order.getNetworkEmpId()), "您不是当前工单的工程师，无法申请结单！");
        Assert.isTrue(order.getStatus() == WorkConstant.WORK_STATUS_3, "当前工单不是 处理中 流程，无法申请结单！");
        // 判断是否为工程师
        boolean manager = empRelation.getManager() || empRelation.getSuperManager();
        if (!manager) {
            // 校验工单是否转单或转单待审核
            boolean hasWaitOrder = workChangeEngineerService.isApplyChangeEngineerWaitCheck(workId);
            Assert.isFalse(hasWaitOrder, "当前工单已申请转单待审核中，禁止操作");
        }
        ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(order.getId(), order.getNetworkId(), loginInfo.getNetworkEmpId());
        ZjWorkModule module = workModuleService.getById(order.getModuleId());
        if (module.getCallPhoneType() == 1) {
            // 查询是否拨打电话
            Assert.isTrue(dispatchEngineer.getCallPhoneQty() > 0, "当前工单已开启必须拨打电话后才能执行后面的操作流程，您当前未拨打过电话，请拨打电话后再操作");
        }
        // 判断是否预约
        if (module.getReservationTimeType() != 1) {
            Assert.isTrue(dispatchEngineer.getReservation(), "当前您未预约，请预约后再执行签到流程！");
        }
        ZjWorkDetail workDetail = workDetailService.getById(order.getId());
        Assert.isFalse(workDetail.getCancelOrderApply(), "当前工单已申请取消工单，待审核中，不允许申请结单");
        Assert.isFalse(workDetail.getEndOrderApply(), "当前工单已申请结单，待审核中，不允许重复申请");
        Assert.isFalse(workDetail.getChangeNetworkApply(), "当前工单已申请改派服务商，待审核中，不允许申请结单");
        Assert.isTrue(workDetail.getNoReviewApplyWorkSpareNum() <= 0, "当前工单存在未审核备件，不允许申请结单");
        Assert.isTrue(workDetail.getNoReviewApplyWorkFeeNum() <= 0, "当前工单存在未审核服务费用项，不允许申请结单");
        // 非乐开的工单则执行
//        if (!workHoubanYunRelationService.isLaikaiOrder(workId)) {
            // 核销码类型判断 校验核销码
            if (module.getEnableStatementVerifCode()) {
                if(StringUtils.isBlank(statementVo.getStatementWriteOffCode())){
                    Assert.isTrue(false,"核销码不能为空");
                }
                // 随机核销码，且核销码不为空再执行
                if (module.getStatementVerifCodeType() == 1 && StringUtils.isNotBlank(statementVo.getStatementWriteOffCode())) {
                    ZjWorkUser workUser = workUserService.getById(workId);
                    SmsVerificCodeService.checkWriteOffCode(workUser.getPhone(), statementVo.getStatementWriteOffCode());
                }
                //非随机核销码
                if(module.getStatementVerifCodeType() == 2 && StringUtils.isNotBlank(statementVo.getStatementWriteOffCode())){
                    boolean equals = workDetail.getStatementVerifCode().equals(statementVo.getStatementWriteOffCode());
                    Assert.isTrue(equals,"核销码不匹配");
                }
            }
//        }
        ZjNetworkStrategy networkStrategy = networkStrategyService.getById(order.getNetworkId());
        boolean autoReviewEndOrder = null != networkStrategy && networkStrategy.getAutoCheckEndOrder();
        loginInfo.setCustAccId(null == loginInfo.getCustAccId() || 0 == loginInfo.getCustAccId()? order.getCustAccId() : loginInfo.getCustAccId());

        // 服务商
        ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(order.getId(), order.getNetworkId());
        ZjWorkDispatchNetwork newDispatchNetwork = null;
        if (null != dispatchNetwork) {
            newDispatchNetwork = new ZjWorkDispatchNetwork();
            newDispatchNetwork.setId(dispatchNetwork.getId());
            newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_5);
        }
        List<WorkLogVo> networkLogs = new ArrayList<>();
        networkLogs.add(new WorkLogVo(loginInfo, order.getId(), "服务工程师申请结单", "待审核" + (StringUtils.isNotBlank(statementVo.getRemark())? "；备注：" + statementVo.getRemark(): "")));

        ZjWorkOrder workOrder = new ZjWorkOrder();
        workOrder.setId(order.getId());
        workOrder.setNewAdvance(order.getNewAdvance() +1);
        workOrder.setUpdateEmpId(loginInfo.getId());
        workOrder.setUpdateEmp(loginInfo.getName());
        Date date = new Date();
        workOrder.setJdTime(date);
        workOrder.setIsHx(0);

        ZjWorkDetail detail = new ZjWorkDetail();
        detail.setId(order.getId());
        detail.setEndOrderApply(!autoReviewEndOrder);

        ZjWorkFinishOrder finishOrder = new ZjWorkFinishOrder();
        finishOrder.setId(IdWorker.getId());
        finishOrder.setCustAccId(loginInfo.getCustAccId());
        finishOrder.setWorkId(workId);
        finishOrder.setNetworkId(loginInfo.getNetworkId());
        finishOrder.setNetworkEmpId(loginInfo.getNetworkEmpId());
        finishOrder.setStatus(WorkConstant.WORK_FINISH_ORDER_STATUS_1);
        finishOrder.setApplyEmpType(2);
        finishOrder.setApplyEmpId(loginInfo.getId());
        finishOrder.setApplyEmp(loginInfo.getName());
        finishOrder.setApplyRemark(statementVo.getRemark());
        finishOrder.setPrice(new BigDecimal("0.0"));
        finishOrder.setSurePrice(new BigDecimal("0.0"));
        finishOrder.setRevieworEmpId(0L);
        finishOrder.setRevieworEmp("");
        finishOrder.setReviewRemark("");

        ZjWorkDispatchEngineer newDispatchEngineer = new ZjWorkDispatchEngineer();
        newDispatchEngineer.setId(dispatchEngineer.getId());
        newDispatchEngineer.setNetworkEmpFinishTime(ZbDateConvertUtil.dateToDateStr(new Date()));
        newDispatchEngineer.setStatus(WorkConstant.DISPATCH_ENGINEER_STATUS_3);

        if (autoReviewEndOrder) {
            if (null != dispatchNetwork) {
                newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_6);
            }
            workOrder.setStatus(WorkConstant.WORK_STATUS_4);
            workOrder.setSettlementStatus(WorkConstant.WORK_SETTLEMENT_STATUS_1);
            workOrder.setEndTime(new Date());
            workOrder.setEndOrder(true);

            finishOrder.setStatus(WorkConstant.WORK_FINISH_ORDER_STATUS_2);
            finishOrder.setReviewTime(new Date());

            newDispatchEngineer.setStatus(WorkConstant.DISPATCH_ENGINEER_STATUS_4);
            networkLogs.add(new WorkLogVo(loginInfo.getCustAccId(), "系统", order.getId(),"系统自动审核结单", "审核通过"));
        }
        workFinishOrderService.save(finishOrder);
        workFinishOrderTemplateService.save(loginInfo.getCustAccId(), workOrder.getId(), finishOrder.getId(), statementVo.getTemplateVos());
        workOrderService.updateById(workOrder);
        workDetailService.updateById(detail);
        if (null != newDispatchNetwork) {
            workDispatchNetworkService.updateById(newDispatchNetwork);
        }
        workDispatchEngineerService.updateById(newDispatchEngineer);
        if (autoReviewEndOrder) {
            workTotalFeeFreezeService.saveUnfreeze(loginInfo.getCustAccId(), order.getFactoryId(), order.getId());
            factoryOrderDeductionBillService.save(loginInfo.getCustAccId(), order.getFactoryId(), order.getId(), order.getCode(), order.getAllInclusiveFee(), order.getModulePrice());
        }
        WorkServiceLog.saveNetwork(networkLogs);
//        if (autoReviewEndOrder) {
        // 发送结单审核短信
        SendOrderFinishVo receiveVo = new SendOrderFinishVo(WorkUtilService.getOrderReceive(workId));
        receiveVo.setResult("审核结果：已通过");
        receiveVo.setType(workModuleService.getById(order.getModuleId()).getName());
        SmsSendMessageService.sendOrderFinish(loginInfo, receiveVo);
        // 事务提交后执行
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                // 反写到乐开伙伴云
                LKaiPushServiceImpl.pushOrderStatus(workId);
            }
        });
//        }
    }

    // 工单详情-根据工单ID获取工单信息
    @Override
    public NetworkOrderDetailVo getNeworkOrderDetail(AccounLoginInfo loginInfo, Long workId) {
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.isTrue(null != order, "服务工单数据不存在");
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        boolean manager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager());

        // 工单时效
        List<OrderSlaSelectVo> slaSelectVos = new ArrayList<>();
        slaSelectVos.add(new OrderSlaSelectVo(workId, order.getModuleId(), order.getStatus(), order.getAssignEmp(), order.getGmtCreate(), order.getGmtUpdate()));

        NetworkOrderDetailVo vo = getNetworkOrderDetailVo(workId, order);
        vo.setSuspendOrder(order.getSuspendStatus() == 2);
        workSlaUtilService.getOrderSlaInfo(slaSelectVos).forEach(t -> {
            vo.setNodeTimeout(t.isNodeTimeout());
            vo.setNodeTimeoutLength(t.getNodeTimeoutLength());
        });
        if (order.getSignImage() != null) {
            List<String> urls = Arrays.asList(order.getSignImage().split(","));
            vo.setSignImageList(urls);
        }
        vo.setNetworkEngineerId(order.getNetworkEmpId());
        // 查询是否有申请结单的工单
        ZjWorkFinishOrder workFinishOrder = workFinishOrderService.getEndOrderByWorkIdAndNetworkId(workId, loginInfo.getNetworkId());
        vo.setHasApplyFinishOrder(null != workFinishOrder && workFinishOrder.getStatus() == WorkConstant.WORK_FINISH_ORDER_STATUS_1);
        if (null != workFinishOrder) {
            vo.setApplyfinishTime(workFinishOrder.getGmtCreate());
            vo.setFinishOrderApplyEmp(workFinishOrder.getApplyEmp());
            List<WorkFinishOrderTemplateExtend> orderTemplates = workFinishOrderTemplateService.getByWorkFinishOrderId(workFinishOrder.getId());
            List<WorkFinishOrderTemplateFieldValExtend> extendList = workFinishOrderTemplateFieldValService.getByWorkStatementTemplateIds(orderTemplates.stream().map(WorkFinishOrderTemplateExtend::getId).toList());
            vo.setFinishOrderTemplates(orderTemplates.stream().map(template -> {
                WorkFinishOrderTemplateVo templateVo = new WorkFinishOrderTemplateVo();
                templateVo.setTemplate(template.getTemplate());
                templateVo.setFieldVals(extendList.stream().filter(f -> Objects.equals(f.getWorkFinishOrderTemplateId(), template.getId())).map(fieldVal -> {
                    FieldValVo valVo = new FieldValVo();
                    valVo.setId(fieldVal.getId());
                    valVo.setType(fieldVal.getType());
                    valVo.setName(fieldVal.getName());
                    valVo.setOptVos(fieldVal.getVals());
                    return valVo;
                }).toList());
                return templateVo;
            }).toList());
        }
        ZjWorkModule module = workModuleService.getById(order.getModuleId());
        ZjWorkDetail workDetail = workDetailService.getById(workId);
        vo.setHasApplyOrderFeeWaitCheck(workDetail.getNoReviewApplyWorkFeeNum() > 0);
        vo.setHasApplyOrderSpareWaitCheck(workDetail.getNoReviewApplyWorkSpareNum() > 0);
        if (manager) {
            // 判断是否工程师
            vo.setEngineer(Objects.equals(loginInfo.getNetworkEmpId(), order.getNetworkEmpId()));
            ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(workId, loginInfo.getNetworkId());
            Assert.notNull(dispatchNetwork, "当前服务工单不属于当前服务商所有");
            vo.setStatus(dispatchNetwork.getStatus());
            vo.setNetworkReceiveTime(dispatchNetwork.getReceivingOrderTime());

            ZjWorkReassign reassign = workReassignService.getWaitCheckWorkReassign(workId);
            vo.setApplyChangeNetworkWaitCheckOrder(null != reassign && reassign.getStatus() == WorkConstant.WORK_REASSIGN_STATUS_1);
            ZjWorkCancel waitCheckCancelOrder = workCancelService.getWaitCheckCancelOrder(workId);
            vo.setApplyCancelOrderWaitCheck(null != waitCheckCancelOrder && waitCheckCancelOrder.getStatus() == WorkConstant.WORK_CANCEL_STATUS_1);
            vo.setExpectedDate(order.getExpectedDate());
            vo.setExpectedStartTime(order.getExpectedStartTime());
            vo.setExpectedEndTime(order.getExpectedEndTime());
            vo.setServiceDispatchNetworkTime(dispatchNetwork.getDispatchTime());
            vo.setCreateTime(order.getGmtCreate());
            // 待接单
            if (vo.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_1) {
                return vo;
            }
            vo.setCallPhoneType(module.getCallPhoneType());
            ZjWorkDispatchEngineer engineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(workId, loginInfo.getNetworkId(), order.getNetworkEmpId());
            if (null != engineer) {
                ViewNetworkEmpAccount empAccount = viewNetworkEmpAccountService.getById(order.getNetworkEmpId());
                vo.setDispatchEngineerId(engineer.getId());
                vo.setEnginnerName(null != empAccount? empAccount.getName() : "");
                vo.setEnginnerPhone(null != empAccount? empAccount.getPhone() : "");
                vo.setCallPhoneQty(engineer.getCallPhoneQty());
                vo.setWriteCallPhoneResult(engineer.getWriteCallPhoneResult());
                vo.setReservation(engineer.getReservation());
                vo.setSignIn(engineer.getSignIn());
                vo.setReservationDate(ZbDateConvertUtil.dateStrToDate(engineer.getReservationDate()));
                vo.setReservationStartTime(ZbDateConvertUtil.dateStrToDate(engineer.getReservationStartTime()));
                vo.setReservationEndTime(ZbDateConvertUtil.dateStrToDate(engineer.getReservationEndTime()));
                vo.setNetworkDispatchToEnginnerTime(ZbDateConvertUtil.dateStrToDate(engineer.getDispatchTime()));
                vo.setUpdateTime(order.getGmtUpdate());
            }
            if (vo.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_4) {
                ZjWorkChangeEngineer changeEngineer = workChangeEngineerService.getWaitCheckTransferOrderApply(loginInfo.getNetworkId(), workId);
                if (null != changeEngineer) {
                    vo.setWaitCheckOrder(true);
                    vo.setApplyType(1);
                    vo.setWaitCheckApplyTime(changeEngineer.getGmtCreate());
                    vo.setWaitCheckApplyEmp(changeEngineer.getApplyNetworkEmp());
                    vo.setWaitCheckApplyType("工程师申请转单");
                    vo.setApplyRemark(changeEngineer.getApplyRemark());
                }
                return vo;
            }
            if (vo.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_5) {
                return vo;
            }
            if (vo.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_6) {
                vo.setOrderEndTime(order.getEndTime());
                return vo;
            }
            if (vo.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_7) {
                ZjWorkCancel workCancel = workCancelService.getCancelOrderByWorkIdAndNetworkIdWidthNetworkEmpId(workId, loginInfo.getNetworkId(), null);
                if (null != workCancel) {
                    vo.setCancelOrderTime(workCancel.getGmtCreate());
                    vo.setCancelOrderEmp(workCancel.getApplyEmp());
                }
                return vo;
            }
            // 是否退回单
            vo.setIsReturn(order.getIsReturn());
            return vo;
        }
        // 工程师
        ZjWorkChangeEngineer changeEngineer = workChangeEngineerService.getWaitCheckTransferOrderApply(loginInfo.getNetworkId(), workId);
        vo.setEngineerApplyChangeOrder(null != changeEngineer);
        // 待结算
        vo.setWaitSettlement(true);
        vo.setOrderEndTime(order.getEndTime());
        vo.setReceivableMoney(new BigDecimal("0.0"));
        vo.setActualReceivedMoney(new BigDecimal("0.0"));

        ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(workId, loginInfo.getNetworkId(), loginInfo.getNetworkEmpId());
        Assert.notNull(dispatchEngineer, "当前服务工单不属于当前工程师所有");
        vo.setStatus(dispatchEngineer.getStatus());
        vo.setReservation(dispatchEngineer.getReservation());
        vo.setSignIn(dispatchEngineer.getSignIn());
        ViewNetworkEmpAccount empAccount = viewNetworkEmpAccountService.getById(order.getNetworkEmpId());
        vo.setDispatchEngineerId(dispatchEngineer.getId());
        vo.setEnginnerName(null != empAccount? empAccount.getName() : "");
        vo.setEnginnerPhone(null != empAccount? empAccount.getPhone() : "");
        vo.setCallPhoneType(module.getCallPhoneType());
        vo.setCallPhoneQty(dispatchEngineer.getCallPhoneQty());
        vo.setWriteCallPhoneResult(dispatchEngineer.getWriteCallPhoneResult());
        vo.setCreateTime(order.getGmtCreate());
        if (vo.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_1) {
            vo.setNetworkDispatchToEnginnerTime(ZbDateConvertUtil.dateStrToDate(dispatchEngineer.getDispatchTime()));
            vo.setExpectedDate(order.getExpectedDate());
            vo.setExpectedStartTime(order.getExpectedStartTime());
            vo.setExpectedEndTime(order.getExpectedEndTime());
            return vo;
        }
        // 服务中
        if (vo.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_2) {
            vo.setExpectedDate(order.getExpectedDate());
            vo.setExpectedStartTime(order.getExpectedStartTime());
            vo.setExpectedEndTime(order.getExpectedEndTime());
            vo.setReservationDate(ZbDateConvertUtil.dateStrToDate(dispatchEngineer.getReservationDate()));
            vo.setReservationStartTime(ZbDateConvertUtil.dateStrToDate(dispatchEngineer.getReservationStartTime()));
            vo.setReservationEndTime(ZbDateConvertUtil.dateStrToDate(dispatchEngineer.getReservationEndTime()));
            vo.setNetworkDispatchToEnginnerTime(ZbDateConvertUtil.dateStrToDate(dispatchEngineer.getDispatchTime()));
            vo.setUpdateTime(order.getGmtUpdate());
            return vo;
        }
        if (vo.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_3) {
            vo.setApplyfinishTime(workFinishOrder.getGmtCreate());
            vo.setReceivableMoney(new BigDecimal("0.0"));
            vo.setActualReceivedMoney(new BigDecimal("0.0"));
            return vo;
        }
        if (vo.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_4) {
            vo.setOrderEndTime(order.getEndTime());
        }
        if (vo.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_5) {
            ZjWorkCancel workCancel = workCancelService.getCancelOrderByWorkIdAndNetworkIdWidthNetworkEmpId(workId, loginInfo.getNetworkId(), order.getNetworkEmpId());
            if (null != workCancel) {
                vo.setCancelOrderTime(workCancel.getGmtCreate());
                vo.setCancelOrderEmp(workCancel.getApplyEmp());
            }
            return vo;
        }
        return vo;
    }

    private NetworkOrderDetailVo getNetworkOrderDetailVo(Long workId, ZjWorkOrder order) {
        ZjWorkModule module = workModuleService.getById(order.getModuleId());
        ZjWorkLevel workLevel = workLevelService.getById(order.getWorkLevelId());
        ZjWorkUser workUser = workUserService.getById(workId);

        NetworkOrderDetailVo vo = new NetworkOrderDetailVo();
        BeanUtil.copyProperties(order, vo);
        vo.setWorkNo(order.getCode());
        vo.setModule("【" + WorkConverter.moduleTypeConverter(module.getType()) +"】" + module.getName());
        if (null != workLevel) {
            vo.setWorkLevel(workLevel.getName());
            vo.setWorkLevelColor(workLevel.getColor());
        }
        vo.setUserName(workUser.getName());
        vo.setUserPhone(workUser.getPhone());
        vo.setProvince(workUser.getProvince());
        vo.setCity(workUser.getCity());
        vo.setArea(workUser.getArea());
        vo.setTown(workUser.getTown());
        vo.setAddress(workUser.getAddress());
        return vo;
    }

    // 工单详情-根据工单ID获取工单详情内容
    @Override
    public NetworkOrderDetailContentVo getNetworkOrderDetailContent(AccounLoginInfo loginInfo, Long workId) {
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.notNull(order, "服务工单数据不存在");
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        boolean manager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager());

        NetworkOrderDetailContentVo vo = new NetworkOrderDetailContentVo();
        ZjWorkDetail workDetail = workDetailService.getById(workId);
        vo.setContent(workDetail.getContent());
        vo.setImages(workImageService.getByWorkId(workId).stream().map(ZjWorkImage::getImage).toList());

        if (manager) {
            ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(workId, loginInfo.getNetworkId());
            Assert.notNull(dispatchNetwork, "当前服务工单不属于当前服务商所有");
            vo.setDispatchRemark(dispatchNetwork.getRemark());
            if (dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_1 || dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_2) {
                return vo;
            }
            ViewNetworkEmpAccount empAccount = viewNetworkEmpAccountService.getById(order.getNetworkEmpId());
            if (null != empAccount) {
                vo.setEngineerPhone(empAccount.getPhone());
                vo.setEngineerName(empAccount.getName());
            }
            if (dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_7) {
                ZjWorkCancel workCancel = workCancelService.getCancelOrderByWorkIdAndNetworkIdWidthNetworkEmpId(workId, loginInfo.getNetworkId(), null);
                if (null != workCancel)vo.setCancelOrderRemark(workCancel.getApplyRemark());
                return vo;
            }
            return vo;
        }
        ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(workId, loginInfo.getNetworkId(), loginInfo.getNetworkEmpId());
        Assert.notNull(dispatchEngineer, "当前服务工单不属于当前工程师所有");
        vo.setEngineerName(loginInfo.getName());
        vo.setEngineerPhone(loginInfo.getPhone());
        if (dispatchEngineer.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_1) {
            vo.setDispatchRemark(dispatchEngineer.getDispatchRemark());
            return vo;
        }
        if (dispatchEngineer.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_5) {
            ZjWorkCancel workCancel = workCancelService.getCancelOrderByWorkIdAndNetworkIdWidthNetworkEmpId(workId, loginInfo.getNetworkId(), loginInfo.getNetworkEmpId());
            if (null != workCancel) vo.setCancelOrderRemark(workCancel.getApplyRemark());
        }
        return vo;
    }

    // 工单详情-商品
    @Override
    public List<UserOrderGoodsVo> getNetworkOrderDetailGoods(Long workId) {
        List<WorkGoodsExtend> goodsExtendList = workGoodsService.getByWorkId(workId);
        if (CollectionUtil.isEmpty(goodsExtendList)) {
            return new ArrayList<>();
        }
        List<ZjWorkGoodsCode> goodsCodeList = workGoodsCodeService.getByWorkGoodsIds(goodsExtendList.stream().map(WorkGoodsExtend::getId).toList());
        return goodsExtendList.stream().map(good -> {
            UserOrderGoodsVo vo = new UserOrderGoodsVo();
            vo.setGoodsId(good.getGoodsId());
            vo.setGoodsBrand(good.getGoodsBrand());
            vo.setGoodsName(good.getGoodsName());
            vo.setGoodsModel(good.getGoodsModel());
            vo.setGoodsType(good.getGoodsType());
            vo.setGoodsSpecName(good.getGoodsSpecName());
            vo.setGoodsImage(good.getGoodsImage());
            vo.setQty(good.getQty());
            goodsCodeList.stream().filter(f -> Objects.equals(f.getWorkGoodsId(), good.getId())).findFirst().ifPresent(o -> vo.setCode(o.getCode()));
            return vo;
        }).toList();
    }

    // 工单详情-商品-商品编码
    @Override
    public List<String> getNetworkOrderDetailGoodsCode(Long workGoodsId) {
        List<ZjWorkGoodsCode> codeList = workGoodsCodeService.getByWorkGoodsId(workGoodsId);
        return codeList.stream().map(ZjWorkGoodsCode::getCode).toList();
    }

    // 获取预约时间范围
    @Override
    public Object getNetworkReservationTimeRange(Long workId) {
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.isTrue(null != order, "工单数据不存在");
        ZjWorkModule module = workModuleService.getById(order.getModuleId());

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("reservationTimeType", module.getReservationTimeType());
        resultMap.put("reservationStartTime", ZbDateConvertUtil.DateToHourMinuteStr(module.getReservationStartTime()));
        resultMap.put("reservationEndTime", ZbDateConvertUtil.DateToHourMinuteStr(module.getReservationEndTime()));
        return resultMap;
    }

    // 触发拨打电话的保存
    @Override
    public void saveTriggerCallPhone(AccounLoginInfo loginInfo, Long workId) {
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.isTrue(null != order, "工单数据不存在");
        Assert.isTrue(order.getStatus() == WorkConstant.WORK_STATUS_3,
                order.getStatus() == WorkConstant.WORK_STATUS_1? "当前工单未派单，不允许跨流程拨打电话" :
                        order.getStatus() == WorkConstant.WORK_STATUS_2? "当前工单派单的服务商未确认接单，不允许跨流程拨打电话" :
                                order.getStatus() == WorkConstant.WORK_STATUS_4? "当前工单已完工，禁止重复拨打电话" : "当前工单已取消，禁止重复拨打电话"
        );
        ZjWorkDetail detail = workDetailService.getById(order.getId());
        Assert.isFalse(detail.getChangeNetworkApply(), "当前工单已申请改派服务商，无法再拨打电话");
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        boolean manager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager());
        if (!manager) {
            // 校验工单是否转单或转单待审核
            boolean hasWaitOrder = workChangeEngineerService.isApplyChangeEngineerWaitCheck(workId);
            Assert.isFalse(hasWaitOrder, "当前工单已申请转单待审核中，禁止操作");
        }
        if (manager) {
            ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(order.getId(), loginInfo.getNetworkId());
            Assert.isTrue(null != dispatchNetwork && Objects.equals(dispatchNetwork.getNetworkId(), loginInfo.getNetworkId()), "当前工单不属于您的服务工单，不允许操作拨打电话");
            Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_1, "当前工单您未确认接单，不允许跨流程拨打电话");
            Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_6, "当前工单【已完成】，不允许拨打电话");
            Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_7, "当前工单【已取消】，不允许拨打电话");
        }
        ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(order.getId(), loginInfo.getNetworkId(), order.getNetworkEmpId());
        Assert.isTrue(null != dispatchEngineer, "当前工单不属于您的服务工单，不允许拨打电话");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单您未确认接单，不允许跨流程拨打电话");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单【已完成】，不允许拨打电话");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单【已取消】，不允许拨打电话");
        ZjWorkOrder updateOrder = new ZjWorkOrder();
        updateOrder.setId(order.getId());
        updateOrder.setNewAdvance(order.getNewAdvance() +1);
        updateOrder.setUpdateEmpId(loginInfo.getId());
        updateOrder.setUpdateEmp(loginInfo.getName());

        // 更新工程师拨打电话
        ZjWorkDispatchEngineer newDispatchEngineer = new ZjWorkDispatchEngineer();
        newDispatchEngineer.setId(dispatchEngineer.getId());
        newDispatchEngineer.setCallPhoneQty(dispatchEngineer.getCallPhoneQty() +1);
        newDispatchEngineer.setCallPhoneTime(ZbDateConvertUtil.dateToDateStr(new Date()));
        workDispatchEngineerService.updateById(newDispatchEngineer);
        workOrderService.updateById(updateOrder);
        WorkServiceLog.saveNetwork(new WorkLogVo(loginInfo, workId, "工程师拨打电话"));
    }

    // 保存拨打电话记录
    @Override
    @Transactional
    public void saveCallPhoneLog(AccounLoginInfo loginInfo, Long workId, WorkCallPhoneLogVo callPhoneLogVo) {
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.isTrue(null != order, "工单数据不存在");
        Assert.isTrue(order.getStatus() == WorkConstant.WORK_STATUS_3,
                order.getStatus() == WorkConstant.WORK_STATUS_1? "当前工单未派单，不允许跨流程拨打电话" :
                        order.getStatus() == WorkConstant.WORK_STATUS_2? "当前工单派单的服务商未确认接单，不允许跨流程拨打电话" :
                                order.getStatus() == WorkConstant.WORK_STATUS_4? "当前工单已完工，禁止重复拨打电话" : "当前工单已取消，禁止重复拨打电话"
        );
        ZjWorkDetail detail = workDetailService.getById(order.getId());
        Assert.isFalse(detail.getChangeNetworkApply(), "当前工单已申请改派服务商，无法再拨打电话");
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        boolean manager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager());
        if (!manager) {
            // 校验工单是否转单或转单待审核
            boolean hasWaitOrder = workChangeEngineerService.isApplyChangeEngineerWaitCheck(workId);
            Assert.isFalse(hasWaitOrder, "当前工单已申请转单待审核中，禁止操作");
        }
        if (manager) {
            ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(order.getId(), loginInfo.getNetworkId());
            Assert.isTrue(null != dispatchNetwork && Objects.equals(dispatchNetwork.getNetworkId(), loginInfo.getNetworkId()), "当前工单不属于您的服务工单，不允许操作拨打电话");
            Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_1, "当前工单您未确认接单，不允许跨流程拨打电话");
            Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_6, "当前工单【已完成】，不允许拨打电话");
            Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_7, "当前工单【已取消】，不允许拨打电话");
        }
        ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(order.getId(), loginInfo.getNetworkId(), order.getNetworkEmpId());
        Assert.isTrue(null != dispatchEngineer, "当前工单不属于您的服务工单，不允许拨打电话");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单您未确认接单，不允许跨流程拨打电话");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单【已完成】，不允许拨打电话");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单【已取消】，不允许拨打电话");
        // 更新工程师拨打电话
        ZjWorkDispatchEngineer newDispatchEngineer = new ZjWorkDispatchEngineer();
        newDispatchEngineer.setId(dispatchEngineer.getId());
        newDispatchEngineer.setWriteCallPhoneResult(true);
        List<WorkLogVo> logVos = new ArrayList<>();
        // 拨打成功
        if (callPhoneLogVo.getCallPhoneResult() == 1) {
            Assert.isTrue(null != callPhoneLogVo.getDate() && null != callPhoneLogVo.getReservationStartTime() && null != callPhoneLogVo.getReservationEndTime(),
                    "拨打成功后的预约时间不能为空");
            newDispatchEngineer.setReservation(true);
            newDispatchEngineer.setReservationDate(ZbDateConvertUtil.dateToDateStr(callPhoneLogVo.getDate()));
            newDispatchEngineer.setReservationStartTime(ZbDateConvertUtil.dateToDateStr(callPhoneLogVo.getReservationStartTime()));
            newDispatchEngineer.setReservationEndTime(ZbDateConvertUtil.dateToDateStr(callPhoneLogVo.getReservationEndTime()));

            ZjWorkDetail workDetail = new ZjWorkDetail();
            workDetail.setId(order.getId());
            workDetail.setReservation(true);
            workDetail.setReservationDate(callPhoneLogVo.getDate());
            workDetail.setReservationStartTime(callPhoneLogVo.getReservationStartTime());
            workDetail.setReservationEndTime(callPhoneLogVo.getReservationEndTime());
            workDetailService.updateById(workDetail);
            if (null != callPhoneLogVo.getDate() && null != callPhoneLogVo.getReservationStartTime() && null != callPhoneLogVo.getReservationEndTime()) {
                String datetime = DateUtil.format(callPhoneLogVo.getDate(), "yyyy-MM-dd") + " " + DateUtil.format(callPhoneLogVo.getReservationStartTime(), "HH:mm") + " ~ " +
                        DateUtil.format(callPhoneLogVo.getReservationEndTime(), "HH:mm");
                logVos.add(new WorkLogVo(loginInfo, workId, "工程师拨打电话", "拨打电话结果：拨打成功；预约上门时间为：" + datetime));
            } else {
                logVos.add(new WorkLogVo(loginInfo, workId, "工程师拨打电话", "拨打电话结果：拨打成功"));
            }
        }
        // 记录下次拨打时间
        if (callPhoneLogVo.getCallPhoneResult() == 2) {
            newDispatchEngineer.setNextCallPhoneDate(callPhoneLogVo.getNextCallPhoneDate());
            newDispatchEngineer.setNextCallPhoneStartTime(callPhoneLogVo.getReservationStartTime());
            newDispatchEngineer.setNextCallPhoneEndTime(callPhoneLogVo.getReservationEndTime());
            if (null != callPhoneLogVo.getNextCallPhoneDate() && null != callPhoneLogVo.getReservationStartTime() && null != callPhoneLogVo.getReservationEndTime()) {
                String datetime = DateUtil.format(callPhoneLogVo.getNextCallPhoneDate(), "yyyy-MM-dd") + " " + DateUtil.format(callPhoneLogVo.getReservationStartTime(), "HH:mm") + " ~ " +
                        DateUtil.format(callPhoneLogVo.getReservationEndTime(), "HH:mm");
                logVos.add(new WorkLogVo(loginInfo, workId, "工程师拨打电话", "拨打电话结果：无人接听；下次拨打时间为：" + datetime));
            }
        }
        if (callPhoneLogVo.getCallPhoneResult() == 3) {
            logVos.add(new WorkLogVo(loginInfo, workId, "工程师拨打电话", "拨打电话结果：其他原因；备注：" + callPhoneLogVo.getRemark()));
        }
        workDispatchEngineerService.updateById(newDispatchEngineer);
        ZjWorkOrder updateOrder = new ZjWorkOrder();
        updateOrder.setId(order.getId());
        updateOrder.setNewAdvance(order.getNewAdvance() +1);
        updateOrder.setUpdateEmpId(loginInfo.getId());
        updateOrder.setUpdateEmp(loginInfo.getName());
        if (callPhoneLogVo.getCallPhoneResult() == 1) {
            updateOrder.setIsCall(1); //已拨电话
        }

        workOrderService.updateById(updateOrder);
        WorkServiceLog.saveNetwork(logVos);

        // 发送短信
        if (callPhoneLogVo.getCallPhoneResult() == 1 && null != callPhoneLogVo.getDate() && null != callPhoneLogVo.getReservationStartTime() && null != callPhoneLogVo.getReservationEndTime()) {
            SendOrderReservationTimeVo reservationTimeVo = new SendOrderReservationTimeVo(WorkUtilService.getOrderReceive(order.getId()));
            reservationTimeVo.setReservationDate(callPhoneLogVo.getDate());
            reservationTimeVo.setReservationStartTime(callPhoneLogVo.getReservationStartTime());
            reservationTimeVo.setReservationEndTime(callPhoneLogVo.getReservationEndTime());
            SmsSendMessageService.sendOrderReservationTime(loginInfo, reservationTimeVo);
        }
        if (callPhoneLogVo.getCallPhoneResult() == 1 && null != callPhoneLogVo.getDate() && null != callPhoneLogVo.getReservationStartTime()) {
            // 事务提交后执行
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    // 反写到乐开伙伴云
                    LKaiPushServiceImpl.pushOrderStatus(workId);
                }
            });
        }
    }

    // 预约时间
    @Override
    @Transactional
    public void networkReservationTime(AccounLoginInfo loginInfo, OrderReservationTimeVo orderReservationTimeVo) {
        ZjWorkOrder order = workOrderService.getById(orderReservationTimeVo.getWorkId());
        Assert.isTrue(null != order, "工单数据不存在");
        Assert.isTrue(order.getStatus() == WorkConstant.WORK_STATUS_3,
                order.getStatus() == WorkConstant.WORK_STATUS_1? "当前工单未派单，不允许预约时间" :
                order.getStatus() == WorkConstant.WORK_STATUS_2? "当前工单派单的服务商未确认接单，不允许预约时间" :
                order.getStatus() == WorkConstant.WORK_STATUS_4? "当前工单已完工，禁止预约时间" : "当前工单已取消，禁止预约时间"
                );
        ZjWorkDetail detail = workDetailService.getById(order.getId());
        Assert.isFalse(detail.getChangeNetworkApply(), "当前工单已申请改派服务商，无法预约时间");

        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        boolean manager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager());
        if (!manager) {
            // 校验工单是否转单或转单待审核
            boolean hasWaitOrder = workChangeEngineerService.isApplyChangeEngineerWaitCheck(orderReservationTimeVo.getWorkId());
            Assert.isFalse(hasWaitOrder, "当前工单已申请转单待审核中，禁止操作");
        }
        if (manager) {
            ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(order.getId(), loginInfo.getNetworkId());
            Assert.isTrue(null != dispatchNetwork && Objects.equals(dispatchNetwork.getNetworkId(), loginInfo.getNetworkId()), "当前工单不属于您的服务工单，不允许操作");
            Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_1, "当前工单您未确认接单，不允许跨流程预约时间");
            Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_6, "当前工单【已完成】，不允许预约时间");
            Assert.isTrue(dispatchNetwork.getStatus() != WorkConstant.DISPATCH_NETWORK_STATUS_7, "当前工单【已取消】，不允许预约时间");
        }
        ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(order.getId(), loginInfo.getNetworkId(), order.getNetworkEmpId());
        Assert.isTrue(null != dispatchEngineer, "当前工单不属于您的服务工单，不允许预约时间");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单您未确认接单，不允许跨流程预约时间");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单【已完成】，不允许预约时间");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单【已取消】，不允许预约时间");

        ZjWorkModule module = workModuleService.getById(order.getModuleId());
        if (module.getCallPhoneType() == 1 && (module.getReservationTimeType() == 2 || module.getReservationTimeType() == 3)) {
            Assert.isTrue(dispatchEngineer.getCallPhoneQty() > 0, "当前工单开启了拨打电话与预约时间，必须先拨打电话填写拨打结果后方可预约时间");
        }
        if (module.getReservationTimeType() == 3) {
            Assert.isTrue((orderReservationTimeVo.getReservationStartTime().after(module.getReservationStartTime()) || orderReservationTimeVo.getReservationStartTime().getTime() == module.getReservationStartTime().getTime())
                            && (orderReservationTimeVo.getReservationEndTime().before(module.getReservationEndTime()) || orderReservationTimeVo.getReservationEndTime().getTime() == module.getReservationEndTime().getTime()),
                    "预约时间必须在【" + DateUtil.format(module.getReservationStartTime(), "HH:mm") + "~" + DateUtil.format(module.getReservationEndTime(), "HH:mm") +"之间");
        }
        String datetime = DateUtil.format(orderReservationTimeVo.getDate(), "yyyy-MM-dd") + " " + DateUtil.format(orderReservationTimeVo.getReservationStartTime(), "HH:mm") + " ~ " +
                DateUtil.format(orderReservationTimeVo.getReservationEndTime(), "HH:mm");

        ZjWorkOrder updateOrder = new ZjWorkOrder();
        updateOrder.setId(order.getId());
        updateOrder.setNewAdvance(order.getNewAdvance() +1);
        updateOrder.setUpdateEmpId(loginInfo.getId());
        updateOrder.setUpdateEmp(loginInfo.getName());
        updateOrder.setCommentTime(orderReservationTimeVo.getLastEndTime());
        if (detail.getReservation() != null && detail.getReservation()) {
            updateOrder.setIsWorkAgain(1);
            updateOrder.setWorkAgainMsg(orderReservationTimeVo.getRemark());
        };

        ZjWorkDetail workDetail = new ZjWorkDetail();
        workDetail.setId(order.getId());
        workDetail.setReservation(true);
        workDetail.setReservationDate(orderReservationTimeVo.getDate());
        workDetail.setReservationStartTime(orderReservationTimeVo.getReservationStartTime());
        workDetail.setReservationEndTime(orderReservationTimeVo.getReservationEndTime());

        if (null == loginInfo.getCustAccId() || loginInfo.getCustAccId() == 0) {
            loginInfo.setCustAccId(order.getCustAccId());
        }
        // 更新工程师预约时间
        ZjWorkDispatchEngineer newDispatchEngineer = new ZjWorkDispatchEngineer();
        newDispatchEngineer.setId(dispatchEngineer.getId());
        newDispatchEngineer.setReservation(true);
        newDispatchEngineer.setReservationDate(ZbDateConvertUtil.dateToDateStr(orderReservationTimeVo.getDate()));
        newDispatchEngineer.setReservationStartTime(ZbDateConvertUtil.dateToDateStr(orderReservationTimeVo.getReservationStartTime()));
        newDispatchEngineer.setReservationEndTime(ZbDateConvertUtil.dateToDateStr(orderReservationTimeVo.getReservationEndTime()));
        newDispatchEngineer.setRemark(orderReservationTimeVo.getRemark());
        workDispatchEngineerService.updateById(newDispatchEngineer);
        workOrderService.updateById(updateOrder);
        workDetailService.updateById(workDetail);
        workReservationLogService.saveNetworkEngineer(loginInfo, new WorkReservationLogVo()
                .setWorkId(orderReservationTimeVo.getWorkId())
                .setReservationDate(orderReservationTimeVo.getDate())
                .setReservationStartTime(orderReservationTimeVo.getReservationStartTime())
                .setReservationEndTime(orderReservationTimeVo.getReservationEndTime())
                .setRemark(orderReservationTimeVo.getRemark()));
        WorkServiceLog.saveNetwork(new WorkLogVo(loginInfo, orderReservationTimeVo.getWorkId(), "工程师预约时间",
                "工程师预约上门时间为：" + datetime + "；" + orderReservationTimeVo.getRemark()));
        // 发送短信
        SendOrderReservationTimeVo reservationTimeVo = new SendOrderReservationTimeVo(WorkUtilService.getOrderReceive(order.getId()));
        reservationTimeVo.setReservationDate(orderReservationTimeVo.getDate());
        reservationTimeVo.setReservationStartTime(orderReservationTimeVo.getReservationStartTime());
        reservationTimeVo.setReservationEndTime(orderReservationTimeVo.getReservationEndTime());
        SmsSendMessageService.sendOrderReservationTime(loginInfo, reservationTimeVo);
        // 事务提交后执行
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                // 反写到乐开伙伴云
                LKaiPushServiceImpl.pushOrderStatus(order.getId());
            }
        });
    }

    // 工程师申请转单/转派工程师
    @Override
    @Transactional
    public void networkApplyTransferEngineer(AccounLoginInfo loginInfo, Long workId, String remark) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        Assert.notNull(empRelation, "您不属于任何服务商人员，禁止该操作");

        ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(workId, loginInfo.getNetworkId());
        Assert.notNull(dispatchNetwork, "当前工单不属于当前服务商的服务工单，禁止转单操作");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_9, "当前工单已改派，禁止转单操作");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_8, "当前工单被服务商已拒绝接单，禁止转单操作");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_1, "当前服务商未确认接单，不允许转单操作");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_6 || dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_7, "当前工单流程已结束，不允许转单操作");
        // 是否有转单待审核的工单
        Assert.isFalse(dispatchNetwork.getTransferOrderWaitCheck(), "当前工单已申请转单，等待审核中，禁止重复申请操作");
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.notNull(order, "服务工单不存在");
        ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(workId, loginInfo.getNetworkId(), order.getNetworkEmpId());
        Assert.notNull(dispatchEngineer, "当前工单不属于您的服务工单，禁止转单操作");
        Assert.isTrue(dispatchEngineer.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_2,
                dispatchEngineer.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_6? "当前工单您已拒绝接单，禁止操作不属于您的工单" :
                dispatchEngineer.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_7? "当前工单您已转单，禁止重复操作" :
                dispatchEngineer.getStatus() == WorkConstant.DISPATCH_ENGINEER_STATUS_8? "当前工单已改派，禁止违反流程操作" : "当前工单处于非[ 服务中 ]流程，禁止违反流程操作");
        ZjWorkDetail detail = workDetailService.getById(workId);
        Assert.isFalse(detail.getChangeNetworkApply(), "当前工单已申请改派服务商，无法申请转派工程师");

        boolean manager = empRelation.getManager() || empRelation.getSuperManager();
        List<WorkLogVo> networkLogs = new ArrayList<>();
        networkLogs.add(new WorkLogVo(loginInfo, workId, "工程师申请转单", "待服务商审核；\r\n备注：" + remark));

        ZjWorkChangeEngineer changeEngineer = new ZjWorkChangeEngineer();
        changeEngineer.setId(IdWorker.getId());
        changeEngineer.setCustAccId(loginInfo.getCustAccId());
        changeEngineer.setWorkId(workId);
        changeEngineer.setNetworkId(loginInfo.getNetworkId());
        changeEngineer.setApplyNetworkEmpId(loginInfo.getNetworkEmpId());
        changeEngineer.setApplyNetworkEmp(loginInfo.getName());
        changeEngineer.setStatus(WorkConstant.WORK_CHANGE_ENGINEER_STATUS_1);
        changeEngineer.setApplyRemark(remark);
        changeEngineer.setReviewEmpType(2);
        if (manager) {
            dispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_2);
            dispatchNetwork.setTransferOrderWaitCheck(false);

            changeEngineer.setStatus(WorkConstant.WORK_CHANGE_ENGINEER_STATUS_2);
            changeEngineer.setReviewEmpId(loginInfo.getId());
            changeEngineer.setReviewEmp(loginInfo.getName());
            changeEngineer.setReviewTime(new Date());
            changeEngineer.setReviewRemark("");

            ZjWorkOrder ZjWorkOrder = new ZjWorkOrder();
            ZjWorkOrder.setId(workId);
            ZjWorkOrder.setNewAdvance(order.getNewAdvance() + 1);
            ZjWorkOrder.setNetworkEmpId(0L);
            workOrderService.updateById(ZjWorkOrder);

            UpdateWrapper<ZjWorkDetail> updateOrderDetailWrapper = new UpdateWrapper<>();
            updateOrderDetailWrapper.eq("id", workId);
            updateOrderDetailWrapper.set("is_reservation", false);
            updateOrderDetailWrapper.set("reservation_date", null);
            updateOrderDetailWrapper.set("reservation_start_time", null);
            updateOrderDetailWrapper.set("reservation_end_time", null);
            updateOrderDetailWrapper.set("engineer_service_time", null);
            workDetailService.update(updateOrderDetailWrapper);

            ZjWorkDispatchEngineer newDispatchEngineer = new ZjWorkDispatchEngineer();
            newDispatchEngineer.setId(dispatchEngineer.getId());
            newDispatchEngineer.setStatus(WorkConstant.DISPATCH_ENGINEER_STATUS_7);
            workDispatchEngineerService.updateById(newDispatchEngineer);
            networkLogs.add(new WorkLogVo(loginInfo, workId, "服务商审核转单", "转单申请已审核通过，待重新派工"));
        } else {
            dispatchNetwork.setTransferOrderWaitCheck(true);

            changeEngineer.setReviewEmpId(0L);
            changeEngineer.setReviewEmp("");
            changeEngineer.setReviewRemark("");
        }
        workChangeEngineerService.save(changeEngineer);
        workDispatchNetworkService.updateById(dispatchNetwork);
        WorkServiceLog.saveNetwork(networkLogs);
    }

    // 服务商审核工程师转单申请
    @Override
    @Transactional
    public void networkCheckTransferEngineer(AccounLoginInfo loginInfo, NetworkMobileCheckTransferEngineerVo transferEngineerVo) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        Assert.notNull(empRelation, "您不属于任何服务商人员，禁止该操作");
        Assert.isTrue(empRelation.getManager() || empRelation.getSuperManager(), "您不是此服务商负责人或管理员，没有权限审核转单申请");

        ZjWorkChangeEngineer changeEngineer = workChangeEngineerService.getWaitCheckTransferOrderApply(loginInfo.getNetworkId(), transferEngineerVo.getWorkId());
        Assert.notNull(changeEngineer, "当前工单没有转单申请");

        ZjWorkOrder order = workOrderService.getById(transferEngineerVo.getWorkId());
        Assert.notNull(order, "工单数据不存在");

        ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(order.getId(), loginInfo.getNetworkId());
        ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(order.getId(), loginInfo.getNetworkId(), order.getNetworkEmpId());

        List<WorkLogVo> networkLogs = new ArrayList<>();
        ZjWorkChangeEngineer newChangeEngineer = new ZjWorkChangeEngineer();
        newChangeEngineer.setId(changeEngineer.getId());

        newChangeEngineer.setReviewEmpType(2);
        newChangeEngineer.setReviewEmpId(loginInfo.getId());
        newChangeEngineer.setReviewEmp(loginInfo.getName());
        newChangeEngineer.setReviewTime(new Date());
        newChangeEngineer.setReviewRemark(StringUtils.isNotBlank(transferEngineerVo.getRemark())? transferEngineerVo.getRemark() : "");

        ZjWorkOrder workOrder = new ZjWorkOrder();
        workOrder.setId(order.getId());
        workOrder.setNewAdvance(order.getNewAdvance() +1);

        ZjWorkDispatchNetwork newDispatchNetwork = new ZjWorkDispatchNetwork();
        newDispatchNetwork.setId(dispatchNetwork.getId());
        newDispatchNetwork.setTransferOrderWaitCheck(false);

        List<ZjWorkDispatchEngineer> addEngineerList = new ArrayList<>();
        List<ZjWorkDispatchEngineer> updateEngineerList = new ArrayList<>();
        ZjWorkDispatchEngineer newDispatchEngineer = new ZjWorkDispatchEngineer();
        newDispatchEngineer.setId(dispatchEngineer.getId());
        // 驳回
        if (!transferEngineerVo.getStatus()) {
            newChangeEngineer.setStatus(WorkConstant.WORK_CHANGE_ENGINEER_STATUS_3);
            networkLogs.add(new WorkLogVo(loginInfo, transferEngineerVo.getWorkId(), "服务商审核工程师转单申请，审核已驳回", StringUtils.isNotBlank(transferEngineerVo.getRemark())? transferEngineerVo.getRemark() : ""));
        } else { // 审核通过
            networkLogs.add(new WorkLogVo(loginInfo, transferEngineerVo.getWorkId(), "服务商审核工程师转单申请，审核已通过",  StringUtils.isNotBlank(transferEngineerVo.getRemark())? transferEngineerVo.getRemark() : ""));
            // 校验工程师
            ViewNetworkEmpAccount empAccount = null;
            if (null != transferEngineerVo.getNetworkEmpId() && transferEngineerVo.getNetworkEmpId() > 0) {
                empAccount = viewNetworkEmpAccountService.getById(transferEngineerVo.getNetworkEmpId());
                Assert.notNull(empAccount, "派工的工程师参数[ " + transferEngineerVo.getNetworkEmpId() + " ]的数据不存在");
                // 判断审核通过后派单是否派到同一人工程师
                Assert.isFalse(Objects.equals(order.getNetworkEmpId(), transferEngineerVo.getNetworkEmpId()), "审核转单通过，不能派单给同一个工程师！");
                newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_3);
                ZjWorkDispatchEngineer engineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(order.getId(), loginInfo.getNetworkId(), transferEngineerVo.getNetworkEmpId());
                ZjWorkDispatchEngineer newEngineer = new ZjWorkDispatchEngineer();

                networkLogs.add(new WorkLogVo(loginInfo, transferEngineerVo.getWorkId(), "服务商负责人已重新派工，等待工程师接单"));

                // 判断管理员是否派单给自己
                if (Objects.equals(loginInfo.getNetworkEmpId(), transferEngineerVo.getNetworkEmpId()) && (empRelation.getManager() || empRelation.getSuperManager())) {
                    newEngineer.setStatus(WorkConstant.DISPATCH_ENGINEER_STATUS_2);
                    newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_4);
                    networkLogs.add(new WorkLogVo(loginInfo.getCustAccId(), empAccount.getName(), transferEngineerVo.getWorkId(), "工程师已确认接单，等待预约服务"));
                } else {
                    newEngineer.setStatus(empAccount.getAutoSureReceiveOrder()? WorkConstant.DISPATCH_ENGINEER_STATUS_2 : WorkConstant.DISPATCH_ENGINEER_STATUS_1);
                    if (empAccount.getAutoSureReceiveOrder()) {
                        newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_4);
                        networkLogs.add(new WorkLogVo(loginInfo.getCustAccId(), empAccount.getName(), transferEngineerVo.getWorkId(), "工程师已确认接单，等待预约服务"));
                    }
                }
                newEngineer.setDispatchTime(ZbDateConvertUtil.dateToDateStr(new Date()));
                newEngineer.setReceivingOrderTime(empAccount.getAutoSureReceiveOrder()? ZbDateConvertUtil.dateToDateStr(new Date()) : "");
                newEngineer.setDispatchRemark(transferEngineerVo.getRemark());
                newEngineer.setReservation(false);
                newEngineer.setReservationDate("");
                newEngineer.setReservationStartTime("");
                newEngineer.setReservationEndTime("");
                newEngineer.setNetworkEmpFinishTime("");
                newEngineer.setRemark("");
                newEngineer.setCallPhoneQty(0);
                newEngineer.setCallPhoneTime("");
                newEngineer.setWriteCallPhoneResult(false);
                newEngineer.setSignIn(false);
                if (null != engineer) {
                    newEngineer.setId(engineer.getId());
                    updateEngineerList.add(newEngineer);
                } else {
                    newEngineer.setId(IdWorker.getId());
                    newEngineer.setCustAccId(loginInfo.getCustAccId());
                    newEngineer.setWorkId(order.getId());
                    newEngineer.setNetworkId(order.getNetworkId());
                    newEngineer.setNetworkEmpId(transferEngineerVo.getNetworkEmpId());
                    addEngineerList.add(newEngineer);
                }
            } else {
                newDispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_2);
            }
            workOrder.setNetworkEmpId(transferEngineerVo.getNetworkEmpId());
            newChangeEngineer.setStatus(WorkConstant.WORK_CHANGE_ENGINEER_STATUS_2);
            newDispatchEngineer.setStatus(WorkConstant.DISPATCH_ENGINEER_STATUS_7);
            updateEngineerList.add(newDispatchEngineer);
            UpdateWrapper<ZjWorkDetail> updateOrderDetailWrapper = new UpdateWrapper<>();
            updateOrderDetailWrapper.eq("id", transferEngineerVo.getWorkId());
            updateOrderDetailWrapper.set("is_reservation", false);
            updateOrderDetailWrapper.set("reservation_date", null);
            updateOrderDetailWrapper.set("reservation_start_time", null);
            updateOrderDetailWrapper.set("reservation_end_time", null);
            updateOrderDetailWrapper.set("engineer_service_time", null);
            workDetailService.update(updateOrderDetailWrapper);
        }
        workChangeEngineerService.updateById(newChangeEngineer);
        workDispatchNetworkService.updateById(newDispatchNetwork);
        if (CollectionUtil.isNotEmpty(addEngineerList)) workDispatchEngineerService.saveBatch(addEngineerList);
        if (CollectionUtil.isNotEmpty(updateEngineerList)) workDispatchEngineerService.updateBatchById(updateEngineerList);
        workOrderService.updateById(workOrder);
        WorkServiceLog.saveNetwork(networkLogs);
    }

    // 申请改派服务商
    @Override
    @Transactional
    public void networkApplyChangeNetwork(AccounLoginInfo loginInfo, Long workId, String remark) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        Assert.notNull(empRelation, "您不属于任何服务商人员，禁止该操作");
        Assert.isTrue(empRelation.getManager() || empRelation.getSuperManager(), "您不是此服务商负责人或管理员，没有权限改派服务商申请");

        ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(workId, loginInfo.getNetworkId());
        Assert.notNull(dispatchNetwork, "当前工单不属性您的服务工单，禁止改派操作");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_9, "当前工单已改派，禁止改派申请");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_8, "当前工单已被服务商拒绝接单，禁止改派申请");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_6 || dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_7, "当前工单流程已结束，禁止改派申请");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_5, "当前工单处理待结单流程，禁止改派申请");
        Assert.isFalse(dispatchNetwork.getStatus() == WorkConstant.DISPATCH_NETWORK_STATUS_1, "当前工单分派的服务商未接单，禁止改派申请");

        ZjWorkDetail detail = workDetailService.getById(workId);
        Assert.notNull(detail, "工单数据不存在");
        Assert.isFalse(detail.getChangeNetworkApply(), "当前工单已申请改派服务，等待客服审核，禁止重复申请");

        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.isTrue(order.getNetworkEmpId() == 0, "当前工单已派工工程师，不允许申请改派服务商");

        ZjWorkReassign reassign = new ZjWorkReassign();
        reassign.setId(IdWorker.getId());
        reassign.setCustAccId(loginInfo.getCustAccId());
        reassign.setWorkId(workId);
        reassign.setCurrentNetworkId(loginInfo.getNetworkId());
        reassign.setChangeToNetworkId(0L);
        reassign.setStatus(WorkConstant.WORK_REASSIGN_STATUS_1);
        reassign.setApplyEmpType(2);
        reassign.setApplyEmpId(loginInfo.getId());
        reassign.setApplyEmp(loginInfo.getName());
        reassign.setApplyRemark(StringUtils.isNotBlank(remark)? remark : "");
        reassign.setCancelRemark("");
        reassign.setReviewEmpType(0);
        reassign.setReviewEmpId(0L);
        reassign.setReviewEmp("");
        reassign.setReviewRemark("");
        workReassignService.save(reassign);

        ZjWorkDetail workDetail = new ZjWorkDetail();
        workDetail.setId(workId);
        workDetail.setChangeNetworkApply(true);
        workDetailService.updateById(workDetail);

        ZjWorkOrder newOrder = new ZjWorkOrder();
        newOrder.setId(workId);
        newOrder.setNewAdvance(order.getNewAdvance() +1);
        newOrder.setWaitCopeEvent(order.getWaitCopeEvent() +1);
        workOrderService.updateById(newOrder);
        WorkServiceLog.saveNetwork(new WorkLogVo(loginInfo, workId, "申请改派服务商", remark));
    }

    // 取消改派服务商申请
    @Override
    public void networkCancelChangeNetworkApply(AccounLoginInfo loginInfo, Long workId, String remark) {
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        Assert.notNull(empRelation, "您不属于任何服务商人员，禁止该操作");
        Assert.isTrue(empRelation.getManager() || empRelation.getSuperManager(), "您不是此服务商负责人或管理员，没有权限取消改派服务商申请");

        ZjWorkReassign reassign = workReassignService.getByNetworkIdAndWorkId(loginInfo.getNetworkId(), workId);
        Assert.notNull(reassign, "当前服务商没有改派服务商申请");
        Assert.isTrue(reassign.getStatus() == WorkConstant.WORK_REASSIGN_STATUS_1, "当前工单的改派服务商申请已审核，无法取消");

        ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(workId, loginInfo.getNetworkId());
        Assert.notNull(dispatchNetwork, "当前工单不属性您的服务工单，没有权限取消改派服务商申请");

        ZjWorkDetail detail = workDetailService.getById(workId);
        Assert.notNull(detail, "工单数据不存在");

        ZjWorkOrder order = workOrderService.getById(workId);

        ZjWorkReassign newReassign = new ZjWorkReassign();
        newReassign.setId(IdWorker.getId());
        newReassign.setStatus(WorkConstant.WORK_REASSIGN_STATUS_4);
        newReassign.setCancelRemark(StringUtils.isNotBlank(remark)? remark : "");
        workReassignService.updateById(newReassign);

        ZjWorkDetail workDetail = new ZjWorkDetail();
        workDetail.setId(workId);
        workDetail.setChangeNetworkApply(false);
        workDetailService.updateById(workDetail);

        ZjWorkOrder newOrder = new ZjWorkOrder();
        newOrder.setId(workId);
        newOrder.setNewAdvance(order.getNewAdvance() +1);
        workOrderService.updateById(newOrder);
        WorkServiceLog.saveNetwork(new WorkLogVo(loginInfo, workId, "服务商取消改派工单", remark));
    }

    // 工程师签到打卡
    @Override
    @Transactional
    public Object networkEngineerSign(AccounLoginInfo loginInfo, Long workId, NetworkMobileEngineerSignVo engineerSignVo) {
        ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getById(engineerSignVo.getDispatchEngineerId());
        Assert.notNull(dispatchEngineer, "当前工单没有派工信息，无法签到");
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.notNull(order, "签到工单参数[ " + workId + " ]的数据不存在");
        Assert.isTrue(order.getStatus() == WorkConstant.WORK_STATUS_3,
                order.getStatus() == WorkConstant.WORK_STATUS_1 ? "工单未派单，禁止跨流程签到" :
                        order.getStatus() == WorkConstant.WORK_STATUS_2 ? "服务商未确认接单，禁止跨流程签到" :
                                order.getStatus() == WorkConstant.WORK_STATUS_4 ? "当前工单已完成，禁止操作签到流程" : "当前工单已取消，禁止操作签到流程"
        );
        Assert.isTrue(Objects.equals(order.getNetworkEmpId(), loginInfo.getNetworkEmpId()), "当前工单不是您服务中的工单，无法操作签到");

        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        // 判断是否为工程师
        boolean manager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager());
        if (!manager) {
            // 校验工单是否转单或转单待审核
            boolean hasWaitOrder = workChangeEngineerService.isApplyChangeEngineerWaitCheck(workId);
            Assert.isFalse(hasWaitOrder, "当前工单已申请转单待审核中，禁止签到操作");
        }
        ZjWorkModule module = workModuleService.getById(order.getModuleId());
        if (module.getCallPhoneType() == 1) {
            // 查询是否拨打电话
            Assert.isTrue(dispatchEngineer.getCallPhoneQty() > 0, "当前工单已开启必须拨打电话后才能执行后面的操作流程，您当前未拨打过电话，请拨打电话后再操作");
        }
        // 判断是否预约
        if (module.getReservationTimeType() != 1) {
            Assert.isTrue(dispatchEngineer.getReservation(), "当前您未预约，请预约后再执行签到流程！");
        }
        ZjWorkDispatchEngineer updateEngineer = new ZjWorkDispatchEngineer();
        updateEngineer.setId(dispatchEngineer.getId());
        updateEngineer.setSignIn(true);
        workDispatchEngineerService.updateById(updateEngineer);

        ZjWorkOrder updateOrder = new ZjWorkOrder();
        updateOrder.setId(workId);
        updateOrder.setNewAdvance(order.getNewAdvance() +1);
        // 保存签到时间
        Date date = new Date();
        updateOrder.setSignTime(date);
        // 是否待核销
        updateOrder.setIsHx(1);
        workOrderService.updateById(updateOrder);

        // 查询工程师是否已签到
        ZjWorkEngineerSign engineerSign = workEngineerSignService.getByWorkDispatchEngineerId(engineerSignVo.getDispatchEngineerId());
        if (null != engineerSign) {
            ZjWorkEngineerSign updateSign = new ZjWorkEngineerSign();
            BeanUtil.copyProperties(engineerSignVo, engineerSign);
            updateSign.setId(engineerSign.getId());
            workEngineerSignService.updateById(updateSign);
        } else {
            engineerSign = new ZjWorkEngineerSign();
            BeanUtil.copyProperties(engineerSignVo, engineerSign);
            engineerSign.setId(IdWorker.getId());
            engineerSign.setCustAccId(loginInfo.getCustAccId());
            engineerSign.setWorkId(workId);
            engineerSign.setNetworkId(loginInfo.getNetworkId());
            engineerSign.setNetworkEmpId(loginInfo.getNetworkEmpId());
            engineerSign.setWorkDispatchEngineerId(engineerSignVo.getDispatchEngineerId());
            engineerSign.setSignInTime(new Date());
            workEngineerSignService.save(engineerSign);
        }
        workEngineerSignAnnexService.save(loginInfo.getCustAccId(), workId, engineerSign.getId(), engineerSignVo.getPaths());
        WorkServiceLog.saveNetwork(new WorkLogVo(loginInfo, workId, "工程师签到", "", engineerSignVo.getPaths()));

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("signUsername", loginInfo.getName());
        resultMap.put("signTime", engineerSign.getSignInTime());
        resultMap.put("signProvince", engineerSign.getSignInProvince());
        resultMap.put("signCity", engineerSign.getSignInCity());
        resultMap.put("signArea", engineerSign.getSignInArea());
        resultMap.put("signTown", engineerSign.getSignInTown());
        resultMap.put("signAddress", engineerSign.getSignInAddress());
        resultMap.put("signAnnexs", engineerSignVo.getPaths());
        // 事务提交后执行
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                // 反写到乐开伙伴云
                LKaiPushServiceImpl.pushOrderStatus(workId);
            }
        });
        return resultMap;
    }

    // 根据工单ID获取是否费用全包
    @Override
    public Boolean getOrderAllInclusiveFeeByWorkId(Long workId) {
        ZjWorkOrder order = workOrderService.getById(workId);
        return null != order && order.getAllInclusiveFee();
    }

    // 保存申请费用
    @Override
    @Transactional
    public void saveApplyFee(AccounLoginInfo loginInfo, Long workId, NetworkMobileOrderFeeVo orderFeeVo) {
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.isTrue(null != order, "工单数据不存在");
        Assert.isTrue(order.getStatus() == WorkConstant.WORK_STATUS_3,
                order.getStatus() == WorkConstant.WORK_STATUS_1? "当前工单未派单，不允许申请费用" :
                        order.getStatus() == WorkConstant.WORK_STATUS_2? "当前工单派单的服务商未确认接单，不允申请费用" :
                                order.getStatus() == WorkConstant.WORK_STATUS_4? "当前工单已完工，禁止申请费用" : "当前工单已取消，禁止申请费用"
        );
        ZjWorkDetail detail = workDetailService.getById(order.getId());
        Assert.isFalse(detail.getChangeNetworkApply(), "当前工单已申请改派服务商，无法申请费用");

        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        // 判断是否为工程师
        boolean manager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager());
        if (!manager) {
            // 校验工单是否转单或转单待审核
            boolean hasWaitOrder = workChangeEngineerService.isApplyChangeEngineerWaitCheck(workId);
            Assert.isFalse(hasWaitOrder, "当前工单已申请转单待审核中，禁止申请费用操作");
        }

        ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(order.getId(), loginInfo.getNetworkId(), order.getNetworkEmpId());
        Assert.isTrue(null != dispatchEngineer, "当前工单不属于您的服务工单，不允许申请费用");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单您未确认接单，不允许跨流程申请费用");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单【已完成】，不允许申请费用");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单【已取消】，不允许申请费用");
        ZjWorkModule module = workModuleService.getById(order.getModuleId());
        if (module.getCallPhoneType() == 1) {
            // 查询是否拨打电话
            Assert.isTrue(dispatchEngineer.getCallPhoneQty() > 0, "当前工单已开启必须拨打电话后才能执行后面的操作流程，您当前未拨打过电话，请拨打电话后再操作");
        }
        // 判断是否预约
        if (module.getReservationTimeType() != 1) {
            Assert.isTrue(dispatchEngineer.getReservation(), "当前您未预约，请预约后再执行申请费用！");
        }
        ViewNetworkEmpDetail networkEmpDetailView = viewNetworkEmpDetailService.getManagerByNetworkId(order.getNetworkId());
        ZjWorkFee fee = new ZjWorkFee();
        fee.setId(IdWorker.getId());
        fee.setCustAccId(loginInfo.getCustAccId());
        fee.setWorkId(workId);
        fee.setWorkNo(order.getCode());
        fee.setCode(ZbOrderNoUtil.orderFeeNo(loginInfo.getCustAccId()));
        fee.setStatus(WorkConstant.WORK_FEE_STATUS_1);
        fee.setNetworkId(order.getNetworkId());
        fee.setNetworkManagerEmpId(networkEmpDetailView.getId());
        fee.setNetworkEngineerEmpId(order.getNetworkEmpId());
        fee.setApplyRemark("");
        fee.setApplyEmpType(WorkConstant.APPLY_OR_CHECK_EMP_TYPE_2);
        fee.setApplyEmpId(loginInfo.getId());
        fee.setApplyEmp(loginInfo.getName());
        fee.setReceive(false);
        fee.setReviewEmpId(0L);
        fee.setReviewEmp("");
        fee.setReviewRemark("");
        workFeeService.save(fee);
        ZjWorkDetail updateWorkDetail = new ZjWorkDetail();
        updateWorkDetail.setId(detail.getId());
        updateWorkDetail.setNoReviewApplyWorkFeeNum(detail.getNoReviewApplyWorkFeeNum() +1);
        workDetailService.updateById(updateWorkDetail);
        workFeeDetailService.saveMobileNetworkFee(loginInfo.getCustAccId(), fee.getId(), order.getId(), orderFeeVo.getOrderFeeDetailVos());
        workOrderService.updateNewAdvanceOrWaitCopeEventById(order.getId(), order.getNewAdvance(), order.getWaitCopeEvent() +1);
        WorkServiceLog.saveNetwork(new WorkLogVo(loginInfo, workId, "申请工单服务费"));
        WorkServiceLog.saveMobileNetworkFeeLog(new WorkFeeLogVo(loginInfo, fee.getWorkId(), fee.getId(), "申请工单服务费"));
    }

    // 保存申请工单配件
    @Override
    @Transactional
    public void saveApplySpare(AccounLoginInfo loginInfo, WorkSpareVo workSpareVo) {
        ZjWorkOrder order = workOrderService.getById(workSpareVo.getWorkId());
        Assert.isTrue(null != order, "工单数据不存在");
        Assert.isTrue(order.getStatus() == WorkConstant.WORK_STATUS_3,
                order.getStatus() == WorkConstant.WORK_STATUS_1? "当前工单未派单，不允许申请工单配件" :
                        order.getStatus() == WorkConstant.WORK_STATUS_2? "当前工单派单的服务商未确认接单，不允申请工单配件" :
                                order.getStatus() == WorkConstant.WORK_STATUS_4? "当前工单已完工，禁止申请工单配件" : "当前工单已取消，禁止申请工单配件"
        );
        ZjWorkDetail detail = workDetailService.getById(order.getId());
        Assert.isFalse(detail.getChangeNetworkApply(), "当前工单已申请改派服务商，无法申请工单配件");

        ZjWorkDispatchEngineer dispatchEngineer = workDispatchEngineerService.getByWorkIdAndNetworkIdAndNetworkEmpId(order.getId(), loginInfo.getNetworkId(), order.getNetworkEmpId());
        Assert.isTrue(null != dispatchEngineer, "当前工单不属于您的服务工单，不允许申请工单配件");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单您未确认接单，不允许跨流程申请工单配件");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单【已完成】，不允许申请工单配件");
        Assert.isTrue(dispatchEngineer.getStatus() != WorkConstant.DISPATCH_ENGINEER_STATUS_1, "当前工单【已取消】，不允许申请工单配件");
        ZjWorkModule module = workModuleService.getById(order.getModuleId());
        if (module.getCallPhoneType() == 1) {
            // 查询是否拨打电话
            Assert.isTrue(dispatchEngineer.getCallPhoneQty() > 0, "当前工单已开启必须拨打电话后才能执行后面的操作流程，您当前未拨打过电话，请拨打电话后再操作");
        }
        // 判断是否预约
        if (module.getReservationTimeType() != 1) {
            Assert.isTrue(dispatchEngineer.getReservation(), "当前您未预约，请预约后再执行申请工单配件");
        }
        ZjNetworkEmpRelation empRelation = networkEmpRelationService.getNetworkEmpIdAndNetworkId(loginInfo.getNetworkEmpId(), loginInfo.getNetworkId());
        // 判断是否为工程师
        boolean manager = null != empRelation && (empRelation.getManager() || empRelation.getSuperManager());
        if (!manager) {
            // 校验工单是否转单或转单待审核
            boolean hasWaitOrder = workChangeEngineerService.isApplyChangeEngineerWaitCheck(workSpareVo.getWorkId());
            Assert.isFalse(hasWaitOrder, "当前工单已申请转单待审核中，禁止申请工单配件操作");
        }
        ViewNetworkEmpDetail networkEmpDetailView = viewNetworkEmpDetailService.getManagerByNetworkId(order.getNetworkId());
        ZjWorkSpare spare = new ZjWorkSpare();
        BeanUtil.copyProperties(workSpareVo, spare);
        spare.setApplyRemark(workSpareVo.getRemark());
        spare.setId(IdWorker.getId());
        spare.setCustAccId(loginInfo.getCustAccId());
        spare.setWorkNo(order.getCode());
        spare.setStatus(WorkConstant.WORK_SPARE_STATUS_1);
        spare.setCode(ZbOrderNoUtil.orderSpareNo(loginInfo.getCustAccId()));
        spare.setNetworkId(order.getNetworkId());
        spare.setNetworkManagerEmpId(networkEmpDetailView.getId());
        spare.setNetworkEngineerEmpId(order.getNetworkEmpId());
        spare.setApplyEmpType(WorkConstant.APPLY_OR_CHECK_EMP_TYPE_2);
        spare.setApplyEmpId(loginInfo.getId());
        spare.setApplyEmp(loginInfo.getName());
        spare.setReceived(false);
        spare.setOldCopeWay(0);
        spare.setReviewEmpId(0L);
        spare.setReviewEmp("");
        spare.setReviewRemark("");
        workSpareService.save(spare);
        ZjWorkDetail updateWorkDetail = new ZjWorkDetail();
        updateWorkDetail.setId(detail.getId());
        updateWorkDetail.setNoReviewApplyWorkSpareNum(detail.getNoReviewApplyWorkSpareNum() +1);
        workDetailService.updateById(updateWorkDetail);
        workSpareReceiptService.save(loginInfo.getCustAccId(), spare.getId(), workSpareVo);
        workSpareMaterialService.save(loginInfo.getCustAccId(), order.getId(), spare.getId(), workSpareVo.getSpareMaterialVos(), workSpareVo.getDelSpareMaterialIds());
        workOrderService.updateNewAdvanceOrWaitCopeEventById(order.getId(), order.getNewAdvance(), order.getWaitCopeEvent() +1);
        WorkServiceLog.saveNetwork(new WorkLogVo(loginInfo, workSpareVo.getWorkId(), "申请工单配件"));
        WorkServiceLog.saveMobileNetworkWorkSpareLog(new WorkSpareLogVo(loginInfo, workSpareVo.getWorkId(), spare.getId(), "申请工单配件"));
    }

    // 获取费用信息
    @Override
    public Map<String, Object> getOrderFeeInfo(Long workId) {
        ZjWorkOrder order = workOrderService.getById(workId);
        Assert.notNull(order, "工单参数的数据不存在：" + workId);
        // 服务费用
        QueryWrapper<ZjWorkFee> workFeeQueryWrapper = new QueryWrapper<>();
        workFeeQueryWrapper.select("id", "code", "gmt_create", "review_time")
                .eq("work_id", workId);
        List<ZjWorkFee> workFeeList = workFeeService.list(workFeeQueryWrapper);
        List<NetowrkOrderDetailFeeVo> orderFees = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(workFeeList)) {
            List<WorkFeeDetailExtend> feeDetailExtends = workFeeDetailService.getByWorkId(workId);
            NetowrkOrderDetailFeeVo feeVo = null;
            for (ZjWorkFee workFee : workFeeList) {
                feeVo = new NetowrkOrderDetailFeeVo();
                feeVo.setCode(workFee.getCode());
                feeVo.setDetailFeeInfoVos(feeDetailExtends.stream().filter(f -> Objects.equals(f.getWorkFeeId(), workFee.getId())).map(fee -> {
                    return new NetowrkOrderDetailFeeInfoVo(fee.getType(), fee.getName(),
                            fee.getPayNetworkPrice().multiply(new BigDecimal(fee.getQty())),
                            fee.getStatus(),
                            workFee.getReviewTime()
                    );
                }).toList());
                orderFees.add(feeVo);
            }
        }
        // 配件费用
        QueryWrapper<ZjWorkSpare> workSpareQueryWrapper = new QueryWrapper<>();
        workSpareQueryWrapper.select("id", "code", "gmt_create", "review_time")
                .eq("work_id", workId);
        List<ZjWorkSpare> spareList = workSpareService.list(workSpareQueryWrapper);
        List<NetowrkOrderDetailFeeVo> spareFees = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(spareList)) {
            List<WorkSpareMaterialExtend> materialExtendList = workSpareMaterialService.getByWorkId(workId);
            NetowrkOrderDetailFeeVo feeVo = null;
            for (ZjWorkSpare spare : spareList) {
                feeVo = new NetowrkOrderDetailFeeVo();
                feeVo.setCode(spare.getCode());
                feeVo.setDetailFeeInfoVos(materialExtendList.stream().filter(f -> Objects.equals(f.getWorkSpareId(), spare.getId())).map(spareFee -> {
                    return new NetowrkOrderDetailFeeInfoVo(spareFee.getType(),
                            spareFee.getName() + " " + spareFee.getModel() + " " + spareFee.getSpecName(),
                            spareFee.getPayNetworkPrice().multiply(new BigDecimal(spareFee.getQty())),
                            spareFee.getStatus(),
                            spareFee.getStatus() == 1? spare.getGmtCreate() : spare.getReviewTime()
                    );
                }).toList());
                spareFees.add(feeVo);
            }
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("orderFees", orderFees);
        resultMap.put("spareFees", spareFees);
        resultMap.put("networkModulePrice", order.getNetworkModulePrice());
        resultMap.put("networkDeductionPrice", order.getNetworkSettlementDeductionPrice());
        return resultMap;
    }

//    @Scheduled(fixedRate = 1200000) // 每5分钟执行一次
//    @Transactional
//    public void checkEngineerOrderTimeout() {
//        // 获取所有待工程师接单的工单
//        QueryWrapper<ZjWorkDispatchEngineer> queryOrderTimeoutWrapper = new QueryWrapper<>();
//        queryOrderTimeoutWrapper.select("id", "work_id","dispatch_time","status","network_id")
//                .eq("status",WorkConstant.DISPATCH_ENGINEER_STATUS_1);
//        List<ZjWorkDispatchEngineer> dispatchEngineers = workDispatchEngineerService.list(queryOrderTimeoutWrapper);
//
//        if (CollectionUtil.isEmpty(dispatchEngineers)) {
//            return;
//        }
//        // 存储 dispatchEngineerWorkIds 中的 work_id
//        Set<Long> dispatchEngineerWorkIds = dispatchEngineers.stream()
//                .map(ZjWorkDispatchEngineer::getWorkId)
//                .collect(Collectors.toSet());
//
//        QueryWrapper<ZjWorkOrder> queryWrapper = new QueryWrapper<>();
//        queryWrapper.select("id", "module_id").in("id", dispatchEngineerWorkIds);
//        List<ZjWorkOrder> orderList = workOrderService.list(queryWrapper);
//
//        // 创建工单ID到模块ID的映射
//        Map<Long, Long> workIdToModuleIdMap = orderList.stream()
//                .collect(Collectors.toMap(
//                        ZjWorkOrder::getId,
//                        ZjWorkOrder::getModuleId,
//                        (existing, replacement) -> existing // 如果有重复的key，保留第一个
//                ));
//
//        Date currentTime = new Date();
//
//        for (ZjWorkDispatchEngineer dispatchEngineer : dispatchEngineers) {
//
//            // 获取对应的模块ID
//            Long moduleId = workIdToModuleIdMap.get(dispatchEngineer.getWorkId());
//            if (moduleId == null) {
//                continue;
//            }
//
//            QueryWrapper<ZjWorkSlaModule> slaModuleWrapper = new QueryWrapper<>();
//            slaModuleWrapper.select("work_sla_id").eq("module_id",moduleId);
//            ZjWorkSlaModule zjWorkSlaModule = zjWorkSlaModuleMapper.selectOne(slaModuleWrapper);
//            if(zjWorkSlaModule == null){
//                continue;
//            }
//            QueryWrapper<ZjWorkSlaCondition> queryOrderConditionWrapper = new QueryWrapper<>();
//            queryOrderConditionWrapper.select("id", "ageing_time")
//                    .eq("type",3).eq("work_sla_id",zjWorkSlaModule.getWorkSlaId());
//            ZjWorkSlaCondition zjWorkSlaCondition = zjWorkSlaConditionMapper.selectOne(queryOrderConditionWrapper);
//            if(zjWorkSlaCondition == null){
//                continue;
//            }
//
//            Date dispatchTime = ZbDateConvertUtil.dateStrToDate(dispatchEngineer.getDispatchTime());
//            if (dispatchTime == null) {
//                continue;
//            }
//            // 检查是否超时未接单，更新工单状态为待服务商确认派单
//            if (dispatchTime != null && currentTime.after(DateUtils.addHours(dispatchTime, zjWorkSlaCondition.getAgeingTime()))) {
//                //  更新工单状态
//                UpdateWrapper<ZjWorkOrder> updateOrderWrapper = new UpdateWrapper<>();
//                updateOrderWrapper.eq("id", dispatchEngineer.getWorkId()).eq("status", WorkConstant.WORK_STATUS_3);
//                updateOrderWrapper.set("status", WorkConstant.WORK_STATUS_2);
//                boolean update = workOrderService.update(updateOrderWrapper);
//
//                if (update) {
//                    // 更新服务商派单状态
//                    ZjWorkDispatchNetwork dispatchNetwork = workDispatchNetworkService.getByWorkIdAndNetowrkId(
//                            dispatchEngineer.getWorkId(), dispatchEngineer.getNetworkId());
//                    if (dispatchNetwork != null) {
//                        dispatchNetwork.setStatus(WorkConstant.DISPATCH_NETWORK_STATUS_2); // 设置为待派工状态
//                        workDispatchNetworkService.updateById(dispatchNetwork);
//                    }
//
//                    // 获取工单信息
//                    ZjWorkOrder order = workOrderService.getById(dispatchEngineer.getWorkId());
//                        // 添加工单日志
//                        List<WorkLogVo> networkLogs = new ArrayList<>();
//                        networkLogs.add(new WorkLogVo(
//                                order.getCustAccId(),
//                                "系统",
//                                order.getId(),
//                                "工程师超过" + zjWorkSlaCondition.getAgeingTime() + "小时未接单",
//                                "工单已自动退回到服务商待派单状态"
//                        ));
//                        WorkServiceLog.saveNetwork(networkLogs);
//                        workDispatchEngineerService.removeById(dispatchEngineer.getId());
//                    }
//                }
//            }
//        }

}